From 976855a3215f4cf45445df9cb992b27374ca59bc Mon Sep 17 00:00:00 2001 From: susha Date: Tue, 17 Aug 2021 16:56:47 +0800 Subject: [PATCH] add i2s platform Signed-off-by: susha --- include/platform/i2s_if.h | 221 ++++++++ support/platform/include/i2s_core.h | 71 +++ support/platform/src/i2s_core.c | 254 +++++++++ support/platform/src/i2s_if.c | 233 +++++++++ .../test/unittest/common/hdf_i2s_test.cpp | 173 +++++++ test/unittest/common/hdf_main_test.c | 6 + test/unittest/platform/common/i2s_test.c | 484 ++++++++++++++++++ test/unittest/platform/common/i2s_test.h | 57 +++ test/unittest/platform/hdf_i2s_entry_test.c | 33 ++ test/unittest/platform/hdf_i2s_entry_test.h | 17 + 10 files changed, 1549 insertions(+) create mode 100644 include/platform/i2s_if.h create mode 100644 support/platform/include/i2s_core.h create mode 100644 support/platform/src/i2s_core.c create mode 100644 support/platform/src/i2s_if.c create mode 100644 support/platform/test/unittest/common/hdf_i2s_test.cpp create mode 100644 test/unittest/platform/common/i2s_test.c create mode 100644 test/unittest/platform/common/i2s_test.h create mode 100644 test/unittest/platform/hdf_i2s_entry_test.c create mode 100644 test/unittest/platform/hdf_i2s_entry_test.h diff --git a/include/platform/i2s_if.h b/include/platform/i2s_if.h new file mode 100644 index 000000000..a5106c689 --- /dev/null +++ b/include/platform/i2s_if.h @@ -0,0 +1,221 @@ +/* + * 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 I2S + * @{ + * + * @brief Defines standard APIs of the (I2S) capabilities. + * + * The I2S module abstracts the I2S capabilities of different system platforms to provide stable APIs + * for driver development. + * This module can create and destroy I2S device handles, read and write I2S data, + * and obtain and set configuration parameters. + * + * @since 1.0 + */ + +/** + * @file i2s_if.h + * + * @brief Defines standard I2S-specific interfaces for driver development. + * + * A driver needs to use the I2S-specific interfaces for data writing and reading + * before performing any operations on an I2S-compliant device. + * + * @since 1.0 + */ + +#ifndef I2S_IF_H +#define I2S_IF_H + +#include "hdf_platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +/** + * @brief Defines the configuration of an I2S device. + * + * @attention The specific I2S controller determines which variables in this structure are supported. + * + * @since 1.0 + */ + +#define I2S_DATA_TRANSFER_PERIOD 20 + +enum I2sSampleRate { + I2S_SAMPLE_RATE_8K = 8, + I2S_SAMPLE_RATE_16K = 16, + I2S_SAMPLE_RATE_32K = 32, + I2S_SAMPLE_RATE_48K = 48, + I2S_SAMPLE_RATE_44_1K = 441, // 44.1k + I2S_SAMPLE_RATE_96K = 96, + I2S_SAMPLE_RATE_192K = 192, +}; + +enum I2sWordWidth { + I2S_WORDWIDTH_8BIT = 8, + I2S_WORDWIDTH_16BIT = 16, + I2S_WORDWIDTH_18BIT = 18, + I2S_WORDWIDTH_20BIT = 20, + I2S_WORDWIDTH_24BIT = 24, + I2S_WORDWIDTH_32BIT = 32, +}; + +enum I2sMode { + I2S_MODE_MASTER_TX_MODE, + I2S_MODE_MASTER_RX_MODE, + I2S_MODE_SLAVE_TX_MODE, + I2S_MODE_SLAVE_RX_MODE, +}; + +enum I2sLoopMode { + I2S_NORMAL_MODE, + I2S_LOOPBACK_MODE, +}; + +enum I2sChannel { + I2S_CHANNEL_LOW_LEFT, + I2S_CHANNEL_LOW_RIGHT, +}; + +enum I2sFrameLen { + I2S_FRAME_LEN_32BIT = 32, + I2S_FRAME_LEN_64BIT = 64, +}; + +enum I2sProtocolType { + I2S_PROTOCOL_I2S_STD, + I2S_PROTOCOL_I2S_MSB, + I2S_PROTOCOL_I2S_LSB, + I2S_PROTOCOL_PCM_STD, + I2S_PROTOCOL_PCM_SHORT, + I2S_PROTOCOL_PCM_LONG, +}; + +enum I2sPcmFscDelay { + I2S_PCM_START_1_CYCLE_BEFORE_MSB, /**< PCM FSC starts one cycle before MSB bit */ + I2S_PCM_START_SYNC_MSB, /**< PCM FSC starts at the same time as MSB bit */ +}; + +enum I2sDataSel { + I2S_RISING_EDGE_TX, + I2S_RISING_EDGE_RX, + I2S_FALLING_EDGE_TX, + I2S_FALLING_EDGE_RX, +}; + +enum I2sChannelMode { + I2S_CHANNEL_MODE_STEREO, + I2S_CHANNEL_MODE_MONO, +}; + +enum I2sChannelIfMode { + I2S_CHANNEL_IF_MODE_I2S, + I2S_CHANNEL_IF_MODE_PCM, +}; + +enum I2sWriteChannel { + I2S_WRITE_CHANNEL_AUDIO, + I2S_WRITE_CHANNEL_OUTPUT, +}; + +enum I2slFsSel { + I2SL_FS_SEL_1024_FS, + I2SL_FS_SEL_512_FS, + I2SL_FS_SEL_320_FS, + I2SL_FS_SEL_256_FS, + I2SL_FS_SEL_128_FS, + I2SL_FS_SEL_64_FS, +}; + + +struct I2sCfg { + enum I2sSampleRate sampleRate; /**< I2S sample rate, 8k,16k,32k... */ + enum I2sWordWidth width; /**< I2S word width, 8bit,16bit,20bit,24bit... */ + enum I2sMode mode; /**< I2S mode, master/slave, tx/rx */ + enum I2sPcmFscDelay syncMode; /**< pcm mode, FSC starts location */ + enum I2sLoopMode loopMode; /**< is loopback */ + enum I2sProtocolType type; /**< I2S protocol type */ + enum I2sChannel channel; + enum I2sFrameLen frameLen; + enum I2sDataSel dataSel; + enum I2sChannelMode channelMode; /**< I2S mode,data channel */ + uint8_t samplePrecision; /**< bit */ + enum I2sChannelIfMode channelIfMode; + uint32_t mclk; /**< KHZ */ + uint32_t bclk; /**< KHZ */ + enum I2sWriteChannel writeChannel; + enum I2slFsSel i2slFsSel; + uint8_t Reserved[2]; +}; + +/** + * @brief Defines the custom I2S transfer message. + * + * @attention The specific I2S controller determines whether speed, delayUs, + * and csChange are supported. + * + * @since 1.0 + */ +struct I2sMsg { + uint8_t *wbuf; /**< Address of the write buffer */ + uint8_t *rbuf; /**< Address of the read buffer */ + uint32_t len; /**< Length of the read and write buffers. The read buffer and the write + * buffer have the same length. */ + uint32_t *pRlen; +}; + + +/** + * @brief Obtains the handle of an I2S controller. + * + * You must call this function before accessing the I2S bus. + * + * @param number Indicates the I2S controller ID. + * + * @return Returns the pointer to the {@link DevHandle} of the I2S controller if the operation is successful; + * returns NULL otherwise. + * @since 1.0 + */ +DevHandle I2sOpen(int16_t number); + + /** + * @brief Releases the handle of an I2S controller. + * + * If you no longer need to access the I2S 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 I2S controller. + * + * @since 1.0 + */ +void I2sClose(DevHandle handle); +void I2sEnable(DevHandle handle); +void I2sDisable(DevHandle handle); +int32_t I2sWrite(DevHandle handle, uint8_t *buf, uint32_t len, uint32_t *pWlen); +int32_t I2sRead(DevHandle handle, uint8_t *buf, uint32_t len, uint32_t *pRlen); +void I2sStartWrite(DevHandle handle); +void I2sStopWrite(DevHandle handle); +void I2sStartRead(DevHandle handle); +void I2sStopRead(DevHandle handle); +void I2sSetCfg(DevHandle handle, struct I2sCfg *cfg); +void I2sGetCfg(DevHandle handle, struct I2sCfg *cfg); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* I2S_IF_H */ +/** @} */ diff --git a/support/platform/include/i2s_core.h b/support/platform/include/i2s_core.h new file mode 100644 index 000000000..f43de1df1 --- /dev/null +++ b/support/platform/include/i2s_core.h @@ -0,0 +1,71 @@ +/* + * 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 I2S_CORE_H +#define I2S_CORE_H + +#include "hdf_base.h" +#include "hdf_device_desc.h" +#include "hdf_dlist.h" +#include "i2s_if.h" +#include "osal_mutex.h" + + +struct I2sCntlr; + +struct I2sCntlrMethod { + int32_t (*GetCfg)(struct I2sCntlr *, struct I2sCfg *); + int32_t (*SetCfg)(struct I2sCntlr *, struct I2sCfg *); + int32_t (*Transfer)(struct I2sCntlr *, struct I2sMsg *); + int32_t (*Open)(struct I2sCntlr *); + int32_t (*Close)(struct I2sCntlr *); + int32_t (*Enable)(struct I2sCntlr *); + int32_t (*Disable)(struct I2sCntlr *); + int32_t (*StartWrite)(struct I2sCntlr *); + int32_t (*StopWrite)(struct I2sCntlr *); + int32_t (*StartRead)(struct I2sCntlr *); + int32_t (*StopRead)(struct I2sCntlr *); +}; + +struct I2sCntlr { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + uint32_t busNum; + uint32_t irqNum; + struct OsalMutex lock; + struct I2sCntlrMethod *method; + void *priv; // private data +}; + +/** + * @brief Turn HdfDeviceObject to an I2sCntlr. + * + * @param device Indicates a HdfDeviceObject. + * + * @return Retrns the pointer of the I2sCntlr on success; returns NULL otherwise. + * @since 1.0 + */ +static inline struct I2sCntlr *I2sCntlrFromDevice(struct HdfDeviceObject *device) +{ + return (device == NULL) ? NULL : (struct I2sCntlr *)device->service; +} + +struct I2sCntlr *I2sCntlrCreate(struct HdfDeviceObject *device); +void I2sCntlrDestroy(struct I2sCntlr *cntlr); +int32_t I2sCntlrStartRead(struct I2sCntlr *cntlr); +int32_t I2sCntlrStopRead(struct I2sCntlr *cntlr); +int32_t I2sCntlrStartWrite(struct I2sCntlr *cntlr); +int32_t I2sCntlrStopWrite(struct I2sCntlr *cntlr); +int32_t I2sCntlrOpen(struct I2sCntlr *cntlr); +int32_t I2sCntlrClose(struct I2sCntlr *cntlr); +int32_t I2sCntlrEnable(struct I2sCntlr *cntlr); +int32_t I2sCntlrDisable(struct I2sCntlr *cntlr); +int32_t I2sCntlrSetCfg(struct I2sCntlr *cntlr, struct I2sCfg *cfg); +int32_t I2sCntlrGetCfg(struct I2sCntlr *cntlr, struct I2sCfg *cfg); +int32_t I2sCntlrTransfer(struct I2sCntlr *cntlr, struct I2sMsg *msg); +#endif /* I2S_CORE_H */ diff --git a/support/platform/src/i2s_core.c b/support/platform/src/i2s_core.c new file mode 100644 index 000000000..3a6760023 --- /dev/null +++ b/support/platform/src/i2s_core.c @@ -0,0 +1,254 @@ +/* + * 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 "i2s_core.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "i2s_if.h" + +#define HDF_LOG_TAG i2s_core + +int32_t I2sCntlrOpen(struct I2sCntlr *cntlr) +{ + int32_t ret; + + if (cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->method == NULL || cntlr->method->Open == NULL) { + HDF_LOGE("%s: Open not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + (void)OsalMutexLock(&(cntlr->lock)); + ret = cntlr->method->Open(cntlr); + (void)OsalMutexUnlock(&(cntlr->lock)); + return ret; +} + +int32_t I2sCntlrClose(struct I2sCntlr *cntlr) +{ + int32_t ret; + + if (cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->method == NULL || cntlr->method->Close == NULL) { + HDF_LOGE("%s: Open not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + (void)OsalMutexLock(&(cntlr->lock)); + ret = cntlr->method->Close(cntlr); + (void)OsalMutexUnlock(&(cntlr->lock)); + return ret; +} + +int32_t I2sCntlrEnable(struct I2sCntlr *cntlr) +{ + int32_t ret; + + if (cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->method == NULL || cntlr->method->Enable == NULL) { + HDF_LOGE("%s: Open not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + (void)OsalMutexLock(&(cntlr->lock)); + ret = cntlr->method->Enable(cntlr); + (void)OsalMutexUnlock(&(cntlr->lock)); + return ret; +} + +int32_t I2sCntlrDisable(struct I2sCntlr *cntlr) +{ + int32_t ret; + + if (cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->method == NULL || cntlr->method->Disable == NULL) { + HDF_LOGE("%s: Open not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + (void)OsalMutexLock(&(cntlr->lock)); + ret = cntlr->method->Disable(cntlr); + (void)OsalMutexUnlock(&(cntlr->lock)); + return ret; +} + +int32_t I2sCntlrStartRead(struct I2sCntlr *cntlr) +{ + int32_t ret; + + if (cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->method == NULL || cntlr->method->StartRead == NULL) { + HDF_LOGE("%s: Open not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + (void)OsalMutexLock(&(cntlr->lock)); + ret = cntlr->method->StartRead(cntlr); + (void)OsalMutexUnlock(&(cntlr->lock)); + return ret; +} + + +int32_t I2sCntlrStopRead(struct I2sCntlr *cntlr) +{ + int32_t ret; + + if (cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->method == NULL || cntlr->method->StopRead == NULL) { + HDF_LOGE("%s: Open not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + (void)OsalMutexLock(&(cntlr->lock)); + ret = cntlr->method->StopRead(cntlr); + (void)OsalMutexUnlock(&(cntlr->lock)); + return ret; +} + +int32_t I2sCntlrStartWrite(struct I2sCntlr *cntlr) +{ + int32_t ret; + + if (cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->method == NULL || cntlr->method->StartWrite == NULL) { + HDF_LOGE("%s: Open not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + (void)OsalMutexLock(&(cntlr->lock)); + ret = cntlr->method->StartWrite(cntlr); + (void)OsalMutexUnlock(&(cntlr->lock)); + return ret; +} + +int32_t I2sCntlrStopWrite(struct I2sCntlr *cntlr) +{ + int32_t ret; + + if (cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->method == NULL || cntlr->method->StopWrite == NULL) { + HDF_LOGE("%s: Open not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + (void)OsalMutexLock(&(cntlr->lock)); + ret = cntlr->method->StopWrite(cntlr); + (void)OsalMutexUnlock(&(cntlr->lock)); + return ret; +} + +int32_t I2sCntlrSetCfg(struct I2sCntlr *cntlr, struct I2sCfg *cfg) +{ + int32_t ret; + + if (cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (cntlr->method == NULL || cntlr->method->SetCfg == NULL) { + HDF_LOGE("%s: not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + + (void)OsalMutexLock(&(cntlr->lock)); + ret = cntlr->method->SetCfg(cntlr, cfg); + (void)OsalMutexUnlock(&(cntlr->lock)); + return ret; +} + +int32_t I2sCntlrGetCfg(struct I2sCntlr *cntlr, struct I2sCfg *cfg) +{ + int32_t ret; + + if (cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (cntlr->method == NULL || cntlr->method->GetCfg == NULL) { + HDF_LOGE("%s: not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + + (void)OsalMutexLock(&(cntlr->lock)); + ret = cntlr->method->GetCfg(cntlr, cfg); + (void)OsalMutexUnlock(&(cntlr->lock)); + return ret; +} + +int32_t I2sCntlrTransfer(struct I2sCntlr *cntlr, struct I2sMsg *msg) +{ + int32_t ret; + + if (cntlr == NULL || msg == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->method == NULL || cntlr->method->Transfer == NULL) { + HDF_LOGE("%s: transfer not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + + (void)OsalMutexLock(&(cntlr->lock)); + ret = cntlr->method->Transfer(cntlr, msg); + (void)OsalMutexUnlock(&(cntlr->lock)); + return ret; +} + +struct I2sCntlr *I2sCntlrCreate(struct HdfDeviceObject *device) +{ + struct I2sCntlr *cntlr = NULL; + + if (device == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return NULL; + } + + cntlr = (struct I2sCntlr *)OsalMemCalloc(sizeof(*cntlr)); + if (cntlr == NULL) { + HDF_LOGE("%s: OsalMemCalloc error", __func__); + return NULL; + } + cntlr->device = device; + device->service = &(cntlr->service); + (void)OsalMutexInit(&cntlr->lock); + cntlr->priv = NULL; + cntlr->method = NULL; + return cntlr; +} + +void I2sCntlrDestroy(struct I2sCntlr *cntlr) +{ + if (cntlr == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return; + } + + (void)OsalMutexDestroy(&(cntlr->lock)); + cntlr->device = NULL; + cntlr->method = NULL; + cntlr->priv = NULL; + OsalMemFree(cntlr); +} diff --git a/support/platform/src/i2s_if.c b/support/platform/src/i2s_if.c new file mode 100644 index 000000000..d2fb248f7 --- /dev/null +++ b/support/platform/src/i2s_if.c @@ -0,0 +1,233 @@ +/* + * 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 "i2s_if.h" +#include "los_vm_zone.h" +#include "devsvc_manager_clnt.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "osal_time.h" +#include "securec.h" +#include "i2s_core.h" + +#define HDF_LOG_TAG i2s_if +#define HOST_NAME_LEN 32 + +static struct I2sCntlr *I2sGetCntlrByBusNum(uint32_t num) +{ + int ret; + char *name = NULL; + struct I2sCntlr *cntlr = NULL; + + name = (char *)OsalMemCalloc(HOST_NAME_LEN + 1); + if (name == NULL) { + return NULL; + } + ret = snprintf_s(name, HOST_NAME_LEN + 1, HOST_NAME_LEN, "HDF_PLATFORM_I2S_%u", num); + if (ret < 0) { + HDF_LOGE("%s: snprintf_s failed", __func__); + OsalMemFree(name); + return NULL; + } + cntlr = (struct I2sCntlr *)DevSvcManagerClntGetService(name); + OsalMemFree(name); + return cntlr; +} + +void I2sEnable(DevHandle handle) +{ + struct I2sCntlr *cntlr = (struct I2sCntlr *)handle; + if (cntlr == NULL) { + HDF_LOGE("%s: cntlr is null", __func__); + return; + } + + int ret = I2sCntlrEnable(cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sCntlrEnable fail", __func__); + return; + } +} + +void I2sDisable(DevHandle handle) +{ + struct I2sCntlr *cntlr = (struct I2sCntlr *)handle; + if (cntlr == NULL) { + HDF_LOGE("%s: cntlr is null", __func__); + return; + } + + int ret = I2sCntlrDisable(cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sCntlrDisable fail", __func__); + return; + } +} + +void I2sStartWrite(DevHandle handle) +{ + struct I2sCntlr *cntlr = (struct I2sCntlr *)handle; + if (cntlr == NULL) { + HDF_LOGE("%s: cntlr is null", __func__); + return; + } + + int ret = I2sCntlrStartWrite(cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sCntlrStartWrite fail", __func__); + } +} + +void I2sStopWrite(DevHandle handle) +{ + struct I2sCntlr *cntlr = (struct I2sCntlr *)handle; + if (cntlr == NULL) { + HDF_LOGE("%s: cntlr is null", __func__); + return; + } + + int ret = I2sCntlrStopWrite(cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sCntlrStopWrite fail", __func__); + } +} + +void I2sStartRead(DevHandle handle) +{ + struct I2sCntlr *cntlr = (struct I2sCntlr *)handle; + if (cntlr == NULL) { + HDF_LOGE("%s: cntlr is null", __func__); + return; + } + + int ret = I2sCntlrStartRead(cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sStartRead fail", __func__); + } +} + +void I2sStopRead(DevHandle handle) +{ + struct I2sCntlr *cntlr = (struct I2sCntlr *)handle; + if (cntlr == NULL) { + HDF_LOGE("%s: cntlr is null", __func__); + return; + } + + int ret = I2sCntlrStopRead(cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sCntlrStopWrite fail", __func__); + } +} + +int32_t I2sWrite(DevHandle handle, uint8_t *buf, uint32_t len, uint32_t *pWlen) +{ + struct I2sMsg msg = {0}; + if (pWlen == NULL) { + HDF_LOGE("%s: pWlen is null", __func__); + return HDF_FAILURE; + } + *pWlen = 0; + msg.wbuf = buf; + msg.rbuf = NULL; + msg.len = len; + msg.pRlen = pWlen; + do { + OsalMSleep(I2S_DATA_TRANSFER_PERIOD); + int ret = I2sCntlrTransfer((struct I2sCntlr *)handle, &msg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sCntlrTransfer fail", __func__); + } + } while (*pWlen == 0); + + return HDF_SUCCESS; +} + +int32_t I2sRead(DevHandle handle, uint8_t *buf, uint32_t len, uint32_t *pRlen) +{ + struct I2sMsg msg = {0}; + if (pRlen == NULL) { + HDF_LOGE("%s: pRlen is null", __func__); + return HDF_FAILURE; + } + *pRlen = 0; + msg.wbuf = NULL; + msg.rbuf = buf; + msg.len = len; + msg.pRlen = pRlen; + do { + OsalMSleep(I2S_DATA_TRANSFER_PERIOD); + int ret = I2sCntlrTransfer((struct I2sCntlr *)handle, &msg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sCntlrTransfer fail", __func__); + } + } while (*pRlen == 0); + + return HDF_SUCCESS; +} + +DevHandle I2sOpen(int16_t number) +{ + struct I2sCntlr *cntlr = NULL; + + cntlr = I2sGetCntlrByBusNum(number); + if (cntlr == NULL) { + HDF_LOGE("%s: cntlr is null", __func__); + return NULL; + } + + int ret = I2sCntlrOpen(cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sCntlrOpen fail", __func__); + return NULL; + } + + return (DevHandle)cntlr; +} + +void I2sClose(DevHandle handle) +{ + struct I2sCntlr *cntlr = (struct I2sCntlr *)handle; + if (cntlr == NULL) { + HDF_LOGE("%s: cntlr is null", __func__); + return; + } + + int ret = I2sCntlrClose(cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sClose fail", __func__); + } +} + +void I2sSetCfg(DevHandle handle, struct I2sCfg *cfg) +{ + if (handle == NULL || cfg == NULL) { + HDF_LOGE("%s: cntlr or cfg is null", __func__); + return; + } + + struct I2sCntlr *cntlr = (struct I2sCntlr *)handle; + + int ret = I2sCntlrSetCfg(cntlr, cfg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sCntlrSetCfg fail", __func__); + } +} +void I2sGetCfg(DevHandle handle, struct I2sCfg *cfg) +{ + struct I2sCntlr *cntlr = (struct I2sCntlr *)handle; + if (cntlr == NULL || cfg == NULL) { + HDF_LOGE("%s: cntlr or cfg is null", __func__); + return; + } + + int ret = I2sCntlrGetCfg(cntlr, cfg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sCntlrSetCfg fail", __func__); + } +} diff --git a/support/platform/test/unittest/common/hdf_i2s_test.cpp b/support/platform/test/unittest/common/hdf_i2s_test.cpp new file mode 100644 index 000000000..b65059942 --- /dev/null +++ b/support/platform/test/unittest/common/hdf_i2s_test.cpp @@ -0,0 +1,173 @@ +/* + * 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 "hdf_io_service_if.h" + +using namespace testing::ext; + +enum HdfLiteI2sTestCmd { + I2S_SET_CFG_TEST, + I2S_GET_CFG_TEST, + I2S_OPEN_TEST, + I2S_CLOSE_TEST, + I2S_ENABLE_TEST, + I2S_DISABLE_TEST, + I2S_READ_START_TEST, + I2S_WRITE_START_TEST, + I2S_WRITE_TEST, + I2S_WRITE_STOP_TEST, + I2S_READ_TEST, + I2S_READ_STOP_TEST, + I2S_RELIABILITY_TEST, + I2S_RECORD_TEST, + I2S_PLAY_TEST, +}; + +class HdfLiteI2sTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void HdfLiteI2sTest::SetUpTestCase() +{ + HdfTestOpenService(); +} + +void HdfLiteI2sTest::TearDownTestCase() +{ + HdfTestCloseService(); +} + +void HdfLiteI2sTest::SetUp() +{ +} + +void HdfLiteI2sTest::TearDown() +{ +} + +/** + * @tc.name: I2sSetCfgTest001 + * @tc.desc: i2s function test + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(HdfLiteI2sTest, I2sSetCfgTest001, TestSize.Level1) +{ + struct HdfTestMsg msg = {TEST_PAL_I2S_TYPE, I2S_SET_CFG_TEST, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} + +/** + * @tc.name: I2sReadStartTest001 + * @tc.desc: i2s function test + * @tc.type: FUNC + * @tc.requir: + */ +HWTEST_F(HdfLiteI2sTest, I2sReadStartTest001, TestSize.Level1) +{ + struct HdfTestMsg msg = { TEST_PAL_I2S_TYPE, I2S_READ_START_TEST, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} + +/** + * @tc.name: I2sReadTest001 + * @tc.desc: i2s function test + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(HdfLiteI2sTest, I2sReadTest001, TestSize.Level1) +{ + struct HdfTestMsg msg = {TEST_PAL_I2S_TYPE, I2S_READ_TEST, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} + +/** + * @tc.name: I2sReadStopTest001 + * @tc.desc: i2s function test + * @tc.type: FUNC + * @tc.requir: + */ +HWTEST_F(HdfLiteI2sTest, I2sReadStopTest001, TestSize.Level1) +{ + struct HdfTestMsg msg = { TEST_PAL_I2S_TYPE, I2S_READ_STOP_TEST, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} + +/** + * @tc.name: I2sWriteStartTest001 + * @tc.desc: i2s function test + * @tc.type: FUNC + * @tc.requir: + */ +HWTEST_F(HdfLiteI2sTest, I2sWriteStartTest001, TestSize.Level1) +{ + struct HdfTestMsg msg = { TEST_PAL_I2S_TYPE, I2S_WRITE_START_TEST, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} + + +/** + * @tc.name: I2sWriteTest001 + * @tc.desc: i2s function test + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(HdfLiteI2sTest, I2sWriteTest001, TestSize.Level1) +{ + struct HdfTestMsg msg = {TEST_PAL_I2S_TYPE, I2S_WRITE_TEST, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} + + +/** + * @tc.name: I2sWriteStopTest001 + * @tc.desc: i2s function test + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(HdfLiteI2sTest, I2sWriteStopTest001, TestSize.Level1) +{ + struct HdfTestMsg msg = { TEST_PAL_I2S_TYPE, I2S_WRITE_STOP_TEST, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} + +/** + * @tc.name: I2sGetCfgTest001 + * @tc.desc: i2s function test + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(HdfLiteI2sTest, I2sGetCfgTest001, TestSize.Level1) +{ + struct HdfTestMsg msg = {TEST_PAL_I2S_TYPE, I2S_GET_CFG_TEST, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} + +/** + * @tc.name: I2sReliabilityTest001 + * @tc.desc: i2s function test + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(HdfLiteI2sTest, I2sReliabilityTest001, TestSize.Level1) +{ + struct HdfTestMsg msg = {TEST_PAL_I2S_TYPE, I2S_RELIABILITY_TEST, -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 09e56f697..75ae6386a 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_I2S) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I2S) +#include "hdf_i2s_entry_test.h" +#endif #if defined(LOSCFG_DRIVERS_HDF_PLATFORM_ADC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_ADC) #include "hdf_adc_entry_test.h" #endif @@ -73,6 +76,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_I2S) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I2S) + { TEST_PAL_I2S_TYPE, HdfI2sUnitTestEntry }, +#endif #if defined(LOSCFG_DRIVERS_HDF_PLATFORM_ADC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_ADC) { TEST_PAL_ADC_TYPE, HdfAdcTestEntry }, #endif diff --git a/test/unittest/platform/common/i2s_test.c b/test/unittest/platform/common/i2s_test.c new file mode 100644 index 000000000..09935381d --- /dev/null +++ b/test/unittest/platform/common/i2s_test.c @@ -0,0 +1,484 @@ +/* + * 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 "i2s_test.h" +#include +#include "device_resource_if.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "osal_time.h" +#include "osal_file.h" +#include "osal_test_type.h" +#include "i2s_if.h" + +#define HDF_LOG_TAG i2s_test_c + +#define TEST_READ_FILE_PATH_NAME "/nfs/i2s.wav" +#define TEST_WRITE_FILE_PATH_NAME "/nfs/i2s1.wav" +#define I2S_DATA_BUF_SIZE 0x1000 + +struct I2sTestFunc { + enum I2sTestCmd type; + int32_t (*Func)(struct I2sTest *test); +}; + +static int32_t I2sSetCfgTest(struct I2sTest *test) +{ + if (test == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + HDF_LOGE("%s:sampleRate[%u], type[%u], channelMode[%u], samplePrecision[%u], \ + channelIfMode[%u], mclk[%u], bclk[%u], writeChannel[%u], i2slFsSel[%u]", __func__, + test->sampleRate, test->type, test->channelMode, test->samplePrecision, + test->channelIfMode, test->mclk, test->bclk, test->writeChannel, test->i2slFsSel); + + struct I2sCfg cfg; + cfg.sampleRate = test->sampleRate; + cfg.type = test->type; + cfg.channelMode = test->channelMode; + cfg.samplePrecision = test->samplePrecision; + cfg.channelIfMode = test->channelIfMode; + cfg.mclk = test->mclk; + cfg.bclk = test->bclk; + cfg.writeChannel = test->writeChannel; + cfg.i2slFsSel = test->i2slFsSel; + cfg.width = I2S_WORDWIDTH_16BIT; + + I2sSetCfg(test->handle, &cfg); + return HDF_SUCCESS; +} + +static int32_t I2sGetCfgTest(struct I2sTest *test) +{ + if (test == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + struct I2sCfg cfg; + I2sGetCfg(test->handle, &cfg); + + HDF_LOGE("%s:sampleRate[%u], type[%u], channelMode[%u], samplePrecision[%u], \ + channelIfMode[%u], mclk[%u], bclk[%u], writeChannel[%u], i2slFsSel[%u]", __func__, + test->sampleRate, test->type, test->channelMode, test->samplePrecision, + test->channelIfMode, test->mclk, test->bclk, test->writeChannel, test->i2slFsSel); + return HDF_SUCCESS; +} + +static int32_t I2sOpenTest(struct I2sTest *test) +{ + if (test == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + return HDF_SUCCESS; +} + +static int32_t I2sCloseTest(struct I2sTest *test) +{ + if (test == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + return HDF_SUCCESS; +} + +static int32_t I2sEnableTest(struct I2sTest *test) +{ + if (test == NULL || test->handle == NULL || test->wbuf == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + I2sEnable(test->handle); + return HDF_SUCCESS; +} + +static int32_t I2sDisableTest(struct I2sTest *test) +{ + if (test == NULL || test->handle == NULL || test->wbuf == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + I2sDisable(test->handle); + return HDF_SUCCESS; +} + +#define I2S_WRITE_BUFF_SIZE 0x2000 +static int32_t I2sPlayTest(struct I2sTest *test) +{ + if (test == NULL || test->handle == NULL || test->wbuf == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + OsalFile file; + int32_t size = OsalFileOpen(&file, TEST_WRITE_FILE_PATH_NAME, O_CREAT | OSAL_O_RDWR, OSAL_S_IREAD); + if (size < 0) { + printf("[%s] OsalFileOpen ret[%d] error\n", __func__, size); + return HDF_FAILURE; + } + + uint32_t totalLen = 0; + uint32_t readBuff = I2S_WRITE_BUFF_SIZE; + do { + size = OsalFileRead(&file, test->wbuf, readBuff); + printf("[%s] read file size[%d]", __func__, size); + if (size > 0) { + totalLen += size; + printf("[%s] I2sPlayTest:len[0x%x] [0x%x] wbuf[0x%x][0x%x][0x%x] [0x%x][0x%x][0x%x]\n", __func__, + size, totalLen, test->wbuf[0], test->wbuf[1], test->wbuf[2], + test->wbuf[size - 3], test->wbuf[size - 2], test->wbuf[size - 1]); + + uint32_t wlen = 0; + int ret = I2sWrite(test->handle, test->wbuf, size, &wlen); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2sPlayTest error", __func__); + return HDF_FAILURE; + } + printf("[%s] [%d] I2sPlayTest wlen[%d]\n", __func__, ret, wlen); + } + } while (size > 0); + + OsalFileClose(&file); + return HDF_SUCCESS; +} + +#define READ_TEST_SLEEP 2 +#define READ_TEST_TIMES 1000 +#define READ_TEST_FILE_SIZE (0x4000 * 10000) + +static int32_t I2sRecordTest(struct I2sTest *test) +{ + if (test == NULL || test->handle == NULL || test->rbuf == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + OsalFile file; + int32_t ret = OsalFileOpen(&file, TEST_READ_FILE_PATH_NAME, O_CREAT | OSAL_O_RDWR, OSAL_S_IWRITE); + if (ret < 0) { + HDF_LOGE("[%s] OsalFileOpen ret[%d] error\n", __func__, ret); + return HDF_FAILURE; + } + + int i = 0; + uint32_t totalLen = 0; + while ((i <= READ_TEST_TIMES) && (totalLen <= READ_TEST_FILE_SIZE)) { + test->len = I2S_DATA_BUF_SIZE; + memset_s( test->rbuf, I2S_DATA_BUF_SIZE, 0xee, I2S_DATA_BUF_SIZE); + if (I2sRead(test->handle, test->rbuf, test->len, &test->len) != HDF_SUCCESS) { + HDF_LOGE("%s: I2sRecordTest error \n", __func__); + return HDF_FAILURE; + } + if (test->len == 0) { + HDF_LOGD("%s: not available data.\n", __func__); + } else { + totalLen += test->len; + ret = OsalFileWrite(&file, test->rbuf, test->len); + if (ret < -1) { + HDF_LOGE("%s: write file error \n", __func__); + OsalFileClose(&file); + return HDF_FAILURE; + } + } + + i++; + } + + OsalFileClose(&file); + return HDF_SUCCESS; +} + +static int32_t I2sReadTest(struct I2sTest *test) +{ + if (test == NULL || test->handle == NULL || test->rbuf == NULL || test->wbuf == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + if (I2sRead(test->handle, test->rbuf, test->len, &test->len) != HDF_SUCCESS) { + HDF_LOGE("%s: I2sRead error \n", __func__); + return HDF_FAILURE; + } + + memcpy_s(test->wbuf, test->len, test->rbuf, test->len); + return HDF_SUCCESS; +} + +static int32_t I2sWriteTest(struct I2sTest *test) +{ + if (test == NULL || test->handle == NULL || test->wbuf == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + if (I2sWrite(test->handle, test->wbuf, test->len, &test->len) != HDF_SUCCESS) { + HDF_LOGE("%s: I2sWriteTest error \n", __func__); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + + +static int32_t I2sWriteStartTest(struct I2sTest *test) +{ + if (test == NULL || test->handle == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + I2sStartWrite(test->handle); + return HDF_SUCCESS; +} + +static int32_t I2sReadStartTest(struct I2sTest *test) +{ + if (test == NULL || test->handle == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + HDF_LOGI("%s: rbuf[%p] wbuf[%p]\n", __func__, test->rbuf, test->wbuf); + I2sStartRead(test->handle); + if (test->rbuf != NULL) { + HDF_LOGI("%s: rbuf[0] = [%u]\n", __func__, test->rbuf[0]); + } + + return HDF_SUCCESS; +} + +static int32_t I2sWriteStopTest(struct I2sTest *test) +{ + if (test == NULL || test->handle == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + I2sStopWrite(test->handle); + return HDF_SUCCESS; +} + +static int32_t I2sReadStopTest(struct I2sTest *test) +{ + if (test == NULL || test->handle == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + HDF_LOGI("%s: rbuf[%p] wbuf[%p]\n", __func__, test->rbuf, test->wbuf); + I2sStopRead(test->handle); + if (test->rbuf != NULL) { + HDF_LOGI("%s: rbuf[0] = [%u]\n", __func__, test->rbuf[0]); + } + + return HDF_SUCCESS; +} + +static int32_t I2sReliabilityTest(struct I2sTest *test) +{ + if (test == NULL || test->handle == NULL) { + HDF_LOGE("%s: test null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + (void)I2sSetCfg(test->handle, NULL); + (void)I2sReadTest(NULL); + + (void)test; + HDF_LOGE("%s: success", __func__); + return HDF_SUCCESS; +} + +static struct I2sTestFunc g_i2sTestFunc[] = { + {I2S_SET_CFG_TEST, I2sSetCfgTest}, + {I2S_GET_CFG_TEST, I2sGetCfgTest}, + {I2S_OPEN_TEST, I2sOpenTest}, + {I2S_CLOSE_TEST, I2sCloseTest}, + {I2S_ENABLE_TEST, I2sEnableTest}, + {I2S_DISABLE_TEST, I2sDisableTest}, + {I2S_WRITE_START_TEST, I2sWriteStartTest}, + {I2S_READ_START_TEST, I2sReadStartTest}, + {I2S_WRITE_TEST, I2sWriteTest}, + {I2S_READ_TEST, I2sReadTest}, + {I2S_WRITE_STOP_TEST, I2sWriteStopTest}, + {I2S_READ_STOP_TEST, I2sReadStopTest}, + {I2S_RELIABILITY_TEST, I2sReliabilityTest}, + {I2S_RECORD_TEST, I2sRecordTest}, + {I2S_PLAY_TEST, I2sPlayTest}, +}; + +static int32_t I2sTestEntry(struct I2sTest *test, int32_t cmd) +{ + int32_t i; + int32_t ret = HDF_ERR_NOT_SUPPORT; + + HDF_LOGE("I2s test-- -- -- -- -- -->%s: enter cmd %d", __func__, cmd); + + if (test == NULL) { + HDF_LOGE("%s: test null cmd %d", __func__, cmd); + return HDF_ERR_INVALID_OBJECT; + } + + test->handle = I2sOpen(0); + if (test->handle == NULL) { + HDF_LOGE("%s: i2s test get handle fail", __func__); + return HDF_FAILURE; + } + + for (i = 0; i < sizeof(g_i2sTestFunc) / sizeof(g_i2sTestFunc[0]); i++) { + if (cmd == g_i2sTestFunc[i].type && g_i2sTestFunc[i].Func != NULL) { + ret = g_i2sTestFunc[i].Func(test); + HDF_LOGE("%s: cmd %d ret %d", __func__, cmd, ret); + break; + } + } + + I2sClose(test->handle); + return ret; +} + +static int32_t I2sTestBind(struct HdfDeviceObject *device) +{ + static struct I2sTest test; + + if (device != NULL) { + device->service = &test.service; + } else { + HDF_LOGE("%s: device is NULL", __func__); + } + return HDF_SUCCESS; +} + +static int32_t I2sTestInitFromHcs(struct I2sTest *test, const struct DeviceResourceNode *node) +{ + int32_t ret; + struct DeviceResourceIface *face = NULL; + + face = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (face == NULL) { + HDF_LOGE("%s: face is null", __func__); + return HDF_FAILURE; + } + if (face->GetUint32 == NULL || face->GetUint32Array == NULL) { + HDF_LOGE("%s: GetUint32 or GetUint32Array not support", __func__); + return HDF_ERR_NOT_SUPPORT; + } + ret = face->GetUint8(node, "writeChannel", &test->writeChannel, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read writeChannel fail", __func__); + return HDF_FAILURE; + } + ret = face->GetUint8(node, "i2slFsSel", &test->i2slFsSel, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read i2slFsSel fail", __func__); + return HDF_FAILURE; + } + ret = face->GetUint8(node, "sampleRate", &test->sampleRate, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read sampleRate fail", __func__); + return HDF_FAILURE; + } + ret = face->GetUint8(node, "type", &test->type, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read type fail", __func__); + return HDF_FAILURE; + } + ret = face->GetUint8(node, "channelMode", &test->channelMode, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read channelMode fail", __func__); + return HDF_FAILURE; + } + ret = face->GetUint8(node, "channelIfMode", &test->channelIfMode, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read channelIfMode fail", __func__); + return HDF_FAILURE; + } + ret = face->GetUint8(node, "samplePrecision", &test->samplePrecision, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read samplePrecision fail", __func__); + return HDF_FAILURE; + } + ret = face->GetUint32(node, "MCLK", &test->mclk, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read MCLK fail", __func__); + return HDF_FAILURE; + } + ret = face->GetUint32(node, "BCLK", &test->bclk, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read BCLK fail", __func__); + return HDF_FAILURE; + } + + test->len = I2S_DATA_BUF_SIZE; + test->wbuf = (uint8_t *)OsalMemCalloc(test->len); + if (test->wbuf == NULL) { + HDF_LOGE("%s: wbuf OsalMemCalloc error\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + test->rbuf = (uint8_t *)OsalMemCalloc(test->len); + if (test->rbuf == NULL) { + HDF_LOGE("%s: rbuf OsalMemCalloc error\n", __func__); + OsalMemFree(test->wbuf); + return HDF_ERR_MALLOC_FAIL; + } + return HDF_SUCCESS; +} + +static int32_t I2sTestInit(struct HdfDeviceObject *device) +{ + struct I2sTest *test = NULL; + + if (device == NULL || device->service == NULL || device->property == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + test = (struct I2sTest *)device->service; + if (I2sTestInitFromHcs(test, device->property) != HDF_SUCCESS) { + HDF_LOGE("%s: I2sTestInitFromHcs failed", __func__); + return HDF_FAILURE; + } + + HDF_LOGE("%s: success", __func__); + test->TestEntry = I2sTestEntry; + return HDF_SUCCESS; +} + +static void I2sTestRelease(struct HdfDeviceObject *device) +{ + struct I2sTest *test = NULL; + + if (device == NULL) { + return; + } + test = (struct I2sTest *)device->service; + if (test == NULL) { + return; + } + if (test->wbuf != NULL) { + OsalMemFree(test->wbuf); + } + if (test->rbuf != NULL) { + OsalMemFree(test->rbuf); + } +} + +struct HdfDriverEntry g_i2sTestEntry = { + .moduleVersion = 1, + .Bind = I2sTestBind, + .Init = I2sTestInit, + .Release = I2sTestRelease, + .moduleName = "PLATFORM_I2S_TEST", +}; +HDF_INIT(g_i2sTestEntry); diff --git a/test/unittest/platform/common/i2s_test.h b/test/unittest/platform/common/i2s_test.h new file mode 100644 index 000000000..2c66c521c --- /dev/null +++ b/test/unittest/platform/common/i2s_test.h @@ -0,0 +1,57 @@ +/* + * 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 I2S_TEST_H +#define I2S_TEST_H + +#include "hdf_device_desc.h" +#include "hdf_platform.h" + +enum I2sTestCmd { + I2S_SET_CFG_TEST, + I2S_GET_CFG_TEST, + I2S_OPEN_TEST, + I2S_CLOSE_TEST, + I2S_ENABLE_TEST, + I2S_DISABLE_TEST, + I2S_READ_START_TEST, + I2S_WRITE_START_TEST, + I2S_WRITE_TEST, + I2S_WRITE_STOP_TEST, + I2S_READ_TEST, + I2S_READ_STOP_TEST, + I2S_RELIABILITY_TEST, + I2S_RECORD_TEST, + I2S_PLAY_TEST, +}; + +struct I2sTest { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + int32_t (*TestEntry)(struct I2sTest *test, int32_t cmd); + DevHandle handle; + uint8_t sampleRate; /**< I2S sample rate, 8k,16k,32k... */ + uint8_t type; /**< I2S protocol type */ + uint8_t channelMode; /**< I2S mode,data channel */ + uint8_t samplePrecision; /**< bit */ + uint8_t channelIfMode; + uint8_t writeChannel; + uint8_t i2slFsSel; + uint32_t mclk; /**< KHZ */ + uint32_t bclk; /**< KHZ */ + uint32_t len; + uint8_t *wbuf; + uint8_t *rbuf; +}; + +static inline struct I2sTest *GetI2sTest(void) +{ + return (struct I2sTest *)DevSvcManagerClntGetService("I2S_TEST"); +} + +#endif /* I2S_TEST_H */ diff --git a/test/unittest/platform/hdf_i2s_entry_test.c b/test/unittest/platform/hdf_i2s_entry_test.c new file mode 100644 index 000000000..6721e0002 --- /dev/null +++ b/test/unittest/platform/hdf_i2s_entry_test.c @@ -0,0 +1,33 @@ +/* + * 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_i2s_entry_test.h" +#include "hdf_log.h" +#include "i2s_if.h" +#include "i2s_test.h" + +#define HDF_LOG_TAG hdf_i2s_entry_test + +int32_t HdfI2sUnitTestEntry(HdfTestMsg *msg) +{ + struct I2sTest *test = NULL; + + HDF_LOGE("%s: \n", __func__); + + if (msg == NULL) { + return HDF_FAILURE; + } + test = GetI2sTest(); + if (test == NULL || test->TestEntry == NULL) { + HDF_LOGE("%s: tester is NULL!\n", __func__); + msg->result = HDF_FAILURE; + return HDF_FAILURE; + } + msg->result = test->TestEntry(test, msg->subCmd); + return msg->result; +} diff --git a/test/unittest/platform/hdf_i2s_entry_test.h b/test/unittest/platform/hdf_i2s_entry_test.h new file mode 100644 index 000000000..894623f82 --- /dev/null +++ b/test/unittest/platform/hdf_i2s_entry_test.h @@ -0,0 +1,17 @@ +/* + * 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_I2S_ENTRY_TEST_H +#define HDF_I2S_ENTRY_TEST_H + +#include "hdf_main_test.h" + +int32_t HdfI2sUnitTestEntry(HdfTestMsg *msg); + +#endif /* HDF_I2S_ENTRY_TEST_H */ + -- Gitee