diff --git a/include/platform/i2s_if.h b/include/platform/i2s_if.h
new file mode 100644
index 0000000000000000000000000000000000000000..93757f0ab411269f62c175bbfe5dbd573d8e204a
--- /dev/null
+++ b/include/platform/i2s_if.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2020-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
+ */
+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_441K = 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);
+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 0000000000000000000000000000000000000000..bde47b5985d1f263e1466633387c180507f26db1
--- /dev/null
+++ b/support/platform/include/i2s_core.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020-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 0000000000000000000000000000000000000000..8521c66e42f1d0b14216793309e9118b78d33ae8
--- /dev/null
+++ b/support/platform/src/i2s_core.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2020-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) {
+ 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 0000000000000000000000000000000000000000..21266501eaf2b8bbea86b9ff4be7c514b6ad07e0
--- /dev/null
+++ b/support/platform/src/i2s_if.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2020-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 "devsvc_manager_clnt.h"
+#include "hdf_log.h"
+#include "osal_mem.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)
+{
+ struct I2sMsg msg = {0};
+
+ msg.wbuf = buf;
+ msg.rbuf = NULL;
+ msg.len = len;
+ return I2sCntlrTransfer((struct I2sCntlr *)handle, &msg);
+}
+
+int32_t I2sRead(DevHandle handle, uint8_t *buf, uint32_t len, uint32_t *pRlen)
+{
+ struct I2sMsg msg = {0};
+
+ msg.wbuf = NULL;
+ msg.rbuf = buf;
+ msg.len = len;
+ msg.pRlen = pRlen;
+ I2sCntlrTransfer((struct I2sCntlr *)handle, &msg);
+
+ 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)
+{
+ struct I2sCntlr *cntlr = (struct I2sCntlr *)handle;
+ if (cntlr == NULL || cfg == NULL) {
+ HDF_LOGE("%s: cntlr or cfg is null", __func__);
+ return;
+ }
+
+ 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 0000000000000000000000000000000000000000..50b8beba31d630fa92f867d04dc6a5600aa3e85f
--- /dev/null
+++ b/support/platform/test/unittest/common/hdf_i2s_test.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2020-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_TEST_ALL,
+};
+
+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));
+}
+
+#if 0
+#ifdef HDF_LITEOS_TEST
+/**
+ * @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));
+}
+#endif
+
+#ifdef HDF_LITEOS_TEST
+/**
+ * @tc.name: I2sEnableTest001
+ * @tc.desc: i2s function test
+ * @tc.type: FUNC
+ * @tc.require:
+ */
+HWTEST_F(HdfLiteI2sTest, I2sEnableTest001, TestSize.Level1)
+{
+ struct HdfTestMsg msg = {TEST_PAL_I2S_TYPE, I2S_ENABLE_TEST, -1};
+ EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
+}
+#endif
+
+/**
+ * @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: 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));
+}
+#endif
diff --git a/test/unittest/common/hdf_main_test.c b/test/unittest/common/hdf_main_test.c
index 09e56f6976f4f950f652174040cade96c07a3a52..75ae6386af7bc6ee7eed17dfa1337e544dd486a3 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 0000000000000000000000000000000000000000..84ef14252d808b1b1e3e618c090ee3b87f1b1dbc
--- /dev/null
+++ b/test/unittest/platform/common/i2s_test.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2020-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 "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"
+#include "i2s_test.h"
+
+#define HDF_LOG_TAG i2s_test_c
+
+#define TEST_READ_FILE_PATH_NAME "/nfs/i2s.wav"
+#define TEST_WRITE_FILE_PATH_NAME "/nfs/dynamic.wav"
+
+struct I2sTestFunc {
+ enum I2sTestCmd type;
+ int32_t (*Func)(struct I2sTest *test);
+};
+
+#if 0
+static struct I2sCfg g_I2sCfg = {
+ .i2slFsSel = I2SL_FS_SEL_256_FS,
+};
+#endif
+
+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;
+}
+
+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;
+ }
+
+ int32_t size = -1;
+ OsalFile file;
+
+ 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 = 0x1280;
+ do {
+ size = OsalFileRead(&file, test->wbuf, readBuff);
+ printf("[%s] read file size[%d]", __func__, size);
+ if (size > 0) {
+ totalLen += size;
+ printf("[%s] I2sReadTest: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]);
+
+ if (I2sWrite(test->handle, test->wbuf, size) != HDF_SUCCESS) {
+ HDF_LOGE("%s: I2sRead error", __func__);
+ return HDF_FAILURE;
+ }
+ }
+ } while (size > 0);
+
+ OsalFileClose(&file);
+
+ return HDF_SUCCESS;
+}
+
+static int32_t I2sReadTest(struct I2sTest *test)
+{
+ printf("[%s] I2sReadTest:IN-------->\n", __func__);
+ if (test == NULL) {
+ HDF_LOGE("%s: test null", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+ if (test->handle == NULL) {
+ HDF_LOGE("%s: handle null", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+ if (test->rbuf == NULL) {
+ HDF_LOGE("%s: rbuf null", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+ if (test == NULL || test->handle == NULL || test->rbuf == NULL) {
+ HDF_LOGE("%s: test null", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+
+ sleep(2);
+ printf("[%s] I2sReadTest:begin read-------->\n", __func__);
+
+ int32_t ret = -1;
+ OsalFile file;
+
+ ret = OsalFileOpen(&file, TEST_READ_FILE_PATH_NAME, O_CREAT | OSAL_O_RDWR, OSAL_S_IWRITE);
+ if (ret < 0) {
+ printf("[%s] OsalFileOpen ret[%d] error\n", __func__, ret);
+ return HDF_FAILURE;
+ }
+
+ int i = 0;
+ uint32_t totalLen = 0;
+ while ((i <= 1000) && (totalLen <= (0x140 * 10000))) {
+ if (I2sRead(test->handle, test->rbuf, test->len, &test->len) != HDF_SUCCESS) {
+ HDF_LOGE("%s: I2sRead error", __func__);
+ return HDF_FAILURE;
+ }
+ totalLen += test->len;
+ printf("[%s] I2sReadTest:len[0x%x] [0x%x] i[%d] rbuf[0x%x][0x%x][0x%x][0x%x][0x%x][0x%x]\n", __func__,
+ test->len, totalLen, i, test->rbuf[0], test->rbuf[1], test->rbuf[2],
+ test->rbuf[test->len - 3], test->rbuf[test->len - 2], test->rbuf[test->len - 1]);
+ ret = OsalFileWrite(&file, test->rbuf, test->len);
+ if (ret < -1) {
+ printf("%s: write file error", __func__);
+ OsalFileClose(&file);
+ return HDF_FAILURE;
+ }
+ i++;
+ }
+
+ OsalFileClose(&file);
+ 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 I2sTestAll(struct I2sTest *test)
+{
+ if (test == NULL) {
+ HDF_LOGE("%s: test null", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+ 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_TEST_ALL, I2sTestAll},
+};
+
+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;
+}
+#define I2S_DATA_BUF_SIZE 0x4000
+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;
+ }
+
+ HDF_LOGI("%s: rbuf[%p] wbuf[%p]\n", __func__, test->rbuf, test->wbuf);
+ HDF_LOGI("%s: rbuf[0x%x] [0x%x] [0x%x]\n", __func__, test->rbuf[0], test->rbuf[1], test->rbuf[2]);
+ 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 0000000000000000000000000000000000000000..3d0f601b4bcef6647b6cda9c38eb597fa1b3d9d1
--- /dev/null
+++ b/test/unittest/platform/common/i2s_test.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020-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_TEST_ALL,
+};
+
+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 0000000000000000000000000000000000000000..f2201a9116d6d36e652492d84452a1094a965b3b
--- /dev/null
+++ b/test/unittest/platform/hdf_i2s_entry_test.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020-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 0000000000000000000000000000000000000000..131aedae69a769ef8e65ee0ec307ae1f17b67cbe
--- /dev/null
+++ b/test/unittest/platform/hdf_i2s_entry_test.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020-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 */
+