diff --git a/include/platform/i2s_if.h b/include/platform/i2s_if.h
new file mode 100644
index 0000000000000000000000000000000000000000..a5106c68911062982c678c1799168b1c7a7843e6
--- /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 0000000000000000000000000000000000000000..f43de1df18eddb97331c1e3ea184c1e1ae99a4de
--- /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 0000000000000000000000000000000000000000..3a67600231235a5523e9d2ae84a16866eb4b874e
--- /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 0000000000000000000000000000000000000000..d2fb248f7bd1b69e6afdbf023288fe49e493dbf8
--- /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 0000000000000000000000000000000000000000..b65059942934172d3a93d2389ba861949edc2616
--- /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 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..09935381d57968a30665cc3a7859f0f8e8737e75
--- /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 0000000000000000000000000000000000000000..2c66c521c8fce787e99b879554a361a52d060eda
--- /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 0000000000000000000000000000000000000000..6721e0002009e2ae3098431561ceadcefc3398e7
--- /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 0000000000000000000000000000000000000000..894623f821ae8d14bfe02c8ee5c7d38e32db9065
--- /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 */
+