From 852578d91e59289655189416da757c76ecbba935 Mon Sep 17 00:00:00 2001 From: haizhouyang Date: Thu, 6 May 2021 20:53:43 +0800 Subject: [PATCH 01/21] using mutex as default lock of i2c controller --- support/platform/include/i2c_core.h | 2 -- support/platform/src/i2c_core.c | 28 ++++++++++------------------ 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/support/platform/include/i2c_core.h b/support/platform/include/i2c_core.h index 81208c18..0e5d513a 100644 --- a/support/platform/include/i2c_core.h +++ b/support/platform/include/i2c_core.h @@ -11,7 +11,6 @@ #include "hdf_base.h" #include "i2c_if.h" -#include "osal_atomic.h" #include "osal_mutex.h" #ifdef __cplusplus @@ -28,7 +27,6 @@ struct I2cLockMethod; struct I2cCntlr { struct OsalMutex lock; - OsalAtomic atom; void *owner; int16_t busId; void *priv; diff --git a/support/platform/src/i2c_core.c b/support/platform/src/i2c_core.c index 0ee4f3bd..815e43c4 100644 --- a/support/platform/src/i2c_core.c +++ b/support/platform/src/i2c_core.c @@ -32,20 +32,7 @@ static int32_t I2cCntlrLockDefault(struct I2cCntlr *cntlr) if (cntlr == NULL) { return HDF_ERR_INVALID_OBJECT; } - -__TRY_LOCK: - if (OsalAtomicRead(&cntlr->atom) >= 1) { - OsalAtomicDec(&cntlr->atom); - return HDF_SUCCESS; - } - - if (PlatInIrqContext()) { - OsalMDelay(LOCK_WAIT_SECONDS_M); - } else { - OsalMSleep(LOCK_WAIT_SECONDS_M); - } - - goto __TRY_LOCK; + return OsalMutexLock(&cntlr->lock); } static void I2cCntlrUnlockDefault(struct I2cCntlr *cntlr) @@ -53,8 +40,7 @@ static void I2cCntlrUnlockDefault(struct I2cCntlr *cntlr) if (cntlr == NULL) { return; } - - OsalAtomicInc(&cntlr->atom); + (void)OsalMutexUnlock(&cntlr->lock); } static const struct I2cLockMethod g_i2cLockOpsDefault = { @@ -165,6 +151,8 @@ void I2cCntlrPut(struct I2cCntlr *cntlr) int32_t I2cCntlrAdd(struct I2cCntlr *cntlr) { + int32_t ret; + if (cntlr == NULL) { return HDF_ERR_INVALID_OBJECT; } @@ -183,9 +171,13 @@ int32_t I2cCntlrAdd(struct I2cCntlr *cntlr) HDF_LOGE("I2cCntlrAdd: init lock fail!"); return HDF_FAILURE; } - OsalAtomicSet(&cntlr->atom, 1); - return I2cManagerAddCntlr(cntlr); + ret = I2cManagerAddCntlr(cntlr); + if (ret != HDF_SUCCESS) { + (void)OsalMutexDestroy(&cntlr->lock); + return ret; + } + return HDF_SUCCESS; } void I2cCntlrRemove(struct I2cCntlr *cntlr) From 3ab8a2e9a7bb171efbb87af0f045d72aad78d3bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B7=E9=92=A6=E8=A1=97?= <15390014138@163.com> Date: Thu, 13 May 2021 16:09:22 +0800 Subject: [PATCH 02/21] update support/platform/src/uart_if.c. --- support/platform/src/uart_if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/platform/src/uart_if.c b/support/platform/src/uart_if.c index 94eae00e..88b1dccb 100644 --- a/support/platform/src/uart_if.c +++ b/support/platform/src/uart_if.c @@ -128,7 +128,7 @@ static int32_t UartUserReceive(DevHandle handle, void *data, uint32_t size, enum HDF_LOGE("%s: service is invalid", __func__); return HDF_ERR_INVALID_PARAM; } - /* Four bits are used to store the buffer length, and four bits are used to align the memory. */ + /* Four bytes are used to store the buffer length, and four bytes are used to align the memory. */ reply = HdfSBufObtain(size + sizeof(uint64_t)); if (reply == NULL) { HDF_LOGE("%s: failed to obtain reply", __func__); From 3dc0b8815638b90b1fa71dcb2bbcc881f8837a56 Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 13 May 2021 19:29:49 +0800 Subject: [PATCH 03/21] =?UTF-8?q?IssueNo=EF=BC=9A#I3R803=20Description:mod?= =?UTF-8?q?ify=20sensor=20module=20debug=20information=20Feature=20or=20Bu?= =?UTF-8?q?gfix:Bugfix=20Binary=20Source:=20NO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ib2934b78aef71a152d0afd118f524ab46c4d5c13 --- .../sensor/driver/accel/sensor_accel_driver.c | 5 +-- .../sensor/driver/accel/sensor_accel_driver.h | 2 +- .../driver/chipset/accel/accel_bmi160.c | 39 ++++++++----------- .../common/include/sensor_device_manager.h | 2 +- .../driver/common/include/sensor_parser.h | 2 + .../sensor/driver/common/src/sensor_common.c | 16 ++++---- .../driver/common/src/sensor_device_common.c | 12 +++++- .../driver/common/src/sensor_device_manager.c | 26 ++++++++++--- 8 files changed, 60 insertions(+), 44 deletions(-) diff --git a/model/sensor/driver/accel/sensor_accel_driver.c b/model/sensor/driver/accel/sensor_accel_driver.c index 05bd9d4e..b2d73c95 100644 --- a/model/sensor/driver/accel/sensor_accel_driver.c +++ b/model/sensor/driver/accel/sensor_accel_driver.c @@ -38,7 +38,7 @@ static struct AccelDrvData *AccelGetDrvData(void) static struct SensorRegCfgGroupNode *g_regCfgGroup[SENSOR_GROUP_MAX] = { NULL }; -int32_t RegisterAccelChipOps(struct AccelOpsCall *ops) +int32_t RegisterAccelChipOps(const struct AccelOpsCall *ops) { struct AccelDrvData *drvData = NULL; @@ -131,7 +131,7 @@ static int32_t SetAccelEnable(void) CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_ENABLE_GROUP]); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: accel sensor disable config failed", __func__); + HDF_LOGE("%s: accel sensor enable config failed", __func__); return HDF_FAILURE; } @@ -209,7 +209,6 @@ static int32_t InitAccelOps(struct SensorDeviceInfo *deviceInfo) { struct AccelDrvData *drvData = AccelGetDrvData(); - (void)memset_s((void *)deviceInfo, sizeof(*deviceInfo), 0, sizeof(*deviceInfo)); deviceInfo->ops.GetInfo = SetAccelInfo; deviceInfo->ops.Enable = SetAccelEnable; deviceInfo->ops.Disable = SetAccelDisable; diff --git a/model/sensor/driver/accel/sensor_accel_driver.h b/model/sensor/driver/accel/sensor_accel_driver.h index e28b39ff..c97df8e3 100644 --- a/model/sensor/driver/accel/sensor_accel_driver.h +++ b/model/sensor/driver/accel/sensor_accel_driver.h @@ -59,6 +59,6 @@ struct AccelDrvData { struct AccelOpsCall ops; }; -int32_t RegisterAccelChipOps(struct AccelOpsCall *ops); +int32_t RegisterAccelChipOps(const struct AccelOpsCall *ops); #endif /* SENSOR_ACCEL_DRIVER_H */ diff --git a/model/sensor/driver/chipset/accel/accel_bmi160.c b/model/sensor/driver/chipset/accel/accel_bmi160.c index 669dd0c7..f82c0129 100644 --- a/model/sensor/driver/chipset/accel/accel_bmi160.c +++ b/model/sensor/driver/chipset/accel/accel_bmi160.c @@ -25,9 +25,14 @@ static int32_t ReadBmi160RawData(struct SensorCfgData *data, struct AccelData *r OsalTimespec time; (void)memset_s(&time, sizeof(time), 0, sizeof(time)); - (void)OsalGetTime(&time); + (void)memset_s(®, sizeof(reg), 0, sizeof(reg)); + CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); + if (OsalGetTime(&time) != HDF_SUCCESS) { + HDF_LOGE("%s: Get accel system time failed", __func__); + return HDF_FAILURE; + } *timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT; /* unit nanosecond */ int32_t ret = ReadSensor(&data->busCfg, BMI160_STATUS_ADDR, &status, sizeof(uint8_t)); @@ -36,34 +41,22 @@ static int32_t ReadBmi160RawData(struct SensorCfgData *data, struct AccelData *r } ret = ReadSensor(&data->busCfg, BMI160_ACCEL_X_LSB_ADDR, ®[ACCEL_X_AXIS_LSB], sizeof(uint8_t)); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: i2c read X_AXIS_LSB failed", __func__); - } + CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data"); ret = ReadSensor(&data->busCfg, BMI160_ACCEL_X_MSB_ADDR, ®[ACCEL_X_AXIS_MSB], sizeof(uint8_t)); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: i2c read X_AXIS_MSB failed", __func__); - } + CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data"); ret = ReadSensor(&data->busCfg, BMI160_ACCEL_Y_LSB_ADDR, ®[ACCEL_Y_AXIS_LSB], sizeof(uint8_t)); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: i2c read Y_AXIS_LSB failed", __func__); - } + CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data"); ret = ReadSensor(&data->busCfg, BMI160_ACCEL_Y_MSB_ADDR, ®[ACCEL_Y_AXIS_MSB], sizeof(uint8_t)); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: i2c read Y_AXIS_MSB failed", __func__); - } + CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data"); ret = ReadSensor(&data->busCfg, BMI160_ACCEL_Z_LSB_ADDR, ®[ACCEL_Z_AXIS_LSB], sizeof(uint8_t)); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: i2c read Z_AXIS_LSB failed", __func__); - } + CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data"); ret = ReadSensor(&data->busCfg, BMI160_ACCEL_Z_MSB_ADDR, ®[ACCEL_Z_AXIS_MSB], sizeof(uint8_t)); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: i2c read Z_AXIS_MSB failed", __func__); - } + CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data"); rawData->x = (int16_t)(SENSOR_DATA_SHIFT_LEFT(reg[ACCEL_X_AXIS_MSB], SENSOR_DATA_WIDTH_8_BIT) | reg[ACCEL_X_AXIS_LSB]); @@ -78,7 +71,7 @@ static int32_t ReadBmi160RawData(struct SensorCfgData *data, struct AccelData *r int32_t ReadBmi160Data(struct SensorCfgData *data) { int32_t ret; - struct AccelData rawData = { 0, 0, 0 }; + struct AccelData rawData = { 0, 0, 0 }; int32_t tmp[ACCEL_AXIS_NUM]; struct SensorReportEvent event; @@ -114,7 +107,7 @@ static int32_t InitBmi160(struct SensorCfgData *data) CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: bmi160 sensor init config failed", __func__); + HDF_LOGE("%s: BMI160 sensor init config failed", __func__); return HDF_FAILURE; } return HDF_SUCCESS; @@ -123,11 +116,11 @@ static int32_t InitBmi160(struct SensorCfgData *data) static int32_t InitAccelPreConfig(void) { if (SetSensorPinMux(SENSOR_I2C6_DATA_REG_ADDR, SENSOR_ADDR_WIDTH_4_BYTE, SENSOR_I2C_REG_CFG) != HDF_SUCCESS) { - HDF_LOGE("%s: data write mux pin failed", __func__); + HDF_LOGE("%s: Data write mux pin failed", __func__); return HDF_FAILURE; } if (SetSensorPinMux(SENSOR_I2C6_CLK_REG_ADDR, SENSOR_ADDR_WIDTH_4_BYTE, SENSOR_I2C_REG_CFG) != HDF_SUCCESS) { - HDF_LOGE("%s: clc write mux pin failed", __func__); + HDF_LOGE("%s: ClK write mux pin failed", __func__); return HDF_FAILURE; } diff --git a/model/sensor/driver/common/include/sensor_device_manager.h b/model/sensor/driver/common/include/sensor_device_manager.h index c626ca2b..984b221b 100644 --- a/model/sensor/driver/common/include/sensor_device_manager.h +++ b/model/sensor/driver/common/include/sensor_device_manager.h @@ -13,7 +13,7 @@ #include "sensor_driver_type.h" enum SensorMethodCmd { - SENSOR_CMD_GET_INFO_LIST = 0xFFFF, + SENSOR_CMD_GET_INFO_LIST = 0, SENSOR_CMD_ENABLE = 1, SENSOR_CMD_DISABLE = 2, SENSOR_CMD_SET_BATCH = 3, diff --git a/model/sensor/driver/common/include/sensor_parser.h b/model/sensor/driver/common/include/sensor_parser.h index f3950e37..d69c3225 100644 --- a/model/sensor/driver/common/include/sensor_parser.h +++ b/model/sensor/driver/common/include/sensor_parser.h @@ -15,6 +15,8 @@ #include "sensor_driver_type.h" #include "spi_if.h" +#define SENSOR_CONFIG_MAX_ITEM 100 + enum SensorBusType { SENSOR_BUS_I2C = 0, SENSOR_BUS_SPI = 1, diff --git a/model/sensor/driver/common/src/sensor_common.c b/model/sensor/driver/common/src/sensor_common.c index 0c47fa03..411bf25c 100644 --- a/model/sensor/driver/common/src/sensor_common.c +++ b/model/sensor/driver/common/src/sensor_common.c @@ -27,7 +27,6 @@ int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, uint16_t dataLen) { - uint8_t busType; int index = 0; unsigned char regBuf[I2C_REG_BUF_LEN] = {0}; struct I2cMsg msg[I2C_READ_MSG_NUM]; @@ -35,8 +34,7 @@ int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, CHECK_NULL_PTR_RETURN_VALUE(busCfg, HDF_FAILURE); CHECK_NULL_PTR_RETURN_VALUE(data, HDF_FAILURE); - busType = busCfg->busType; - if (busType == SENSOR_BUS_I2C) { + if (busCfg->busType == SENSOR_BUS_I2C) { CHECK_NULL_PTR_RETURN_VALUE(busCfg->i2cCfg.handle, HDF_FAILURE); (void)memset_s(msg, sizeof(msg), 0, sizeof(msg)); @@ -50,6 +48,9 @@ int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, } else if (busCfg->i2cCfg.regWidth == SENSOR_ADDR_WIDTH_2_BYTE) { regBuf[index++] = (regAddr >> I2C_BYTE_OFFSET) & I2C_BYTE_MASK; regBuf[index++] = regAddr & I2C_BYTE_MASK; + } else { + HDF_LOGE("%s: i2c regWidth[%u] failed", __func__, busCfg->i2cCfg.regWidth); + return HDF_FAILURE; } msg[I2C_READ_MSG_VALUE_IDX].addr = busCfg->i2cCfg.devAddr; @@ -58,7 +59,7 @@ int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, msg[I2C_READ_MSG_VALUE_IDX].buf = data; if (I2cTransfer(busCfg->i2cCfg.handle, msg, I2C_READ_MSG_NUM) != I2C_READ_MSG_NUM) { - HDF_LOGE("%s: i2c[%d] read failed", __func__, busCfg->i2cCfg.busNum); + HDF_LOGE("%s: i2c[%u] read failed", __func__, busCfg->i2cCfg.busNum); return HDF_FAILURE; } } @@ -68,16 +69,13 @@ int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, int32_t WriteSensor(struct SensorBusCfg *busCfg, uint8_t *writeData, uint16_t dataLen) { - uint8_t busType; struct I2cMsg msg[I2C_WRITE_MSG_NUM]; CHECK_NULL_PTR_RETURN_VALUE(busCfg, HDF_FAILURE); CHECK_NULL_PTR_RETURN_VALUE(writeData, HDF_FAILURE); - busType = busCfg->busType; - if (busType == SENSOR_BUS_I2C) { + if (busCfg->busType == SENSOR_BUS_I2C) { CHECK_NULL_PTR_RETURN_VALUE(busCfg->i2cCfg.handle, HDF_FAILURE); - (void)memset_s(msg, sizeof(msg), 0, sizeof(msg)); msg[0].addr = busCfg->i2cCfg.devAddr; msg[0].flags = 0; @@ -85,7 +83,7 @@ int32_t WriteSensor(struct SensorBusCfg *busCfg, uint8_t *writeData, uint16_t da msg[0].buf = writeData; if (I2cTransfer(busCfg->i2cCfg.handle, msg, I2C_WRITE_MSG_NUM) != I2C_WRITE_MSG_NUM) { - HDF_LOGE("%s: i2c[%d] write failed", __func__, busCfg->i2cCfg.busNum); + HDF_LOGE("%s: i2c[%u] write failed", __func__, busCfg->i2cCfg.busNum); return HDF_FAILURE; } } diff --git a/model/sensor/driver/common/src/sensor_device_common.c b/model/sensor/driver/common/src/sensor_device_common.c index 7816aee9..da1e2e85 100644 --- a/model/sensor/driver/common/src/sensor_device_common.c +++ b/model/sensor/driver/common/src/sensor_device_common.c @@ -82,9 +82,8 @@ static int32_t SensorOpsReadCheck(struct SensorBusCfg *busCfg, struct SensorRegC uint16_t mask; uint16_t busMask = 0xffff; int32_t ret; - uint8_t busType = busCfg->busType; - if (busType == SENSOR_BUS_I2C) { + if (busCfg->busType == SENSOR_BUS_I2C) { ret = ReadSensor(busCfg, cfgItem->regAddr, (uint8_t *)&value, sizeof(value)); CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read i2c reg"); busMask = (busCfg->i2cCfg.regWidth == SENSOR_ADDR_WIDTH_1_BYTE) ? 0x00ff : 0xffff; @@ -100,6 +99,8 @@ static int32_t SensorOpsReadCheck(struct SensorBusCfg *busCfg, struct SensorRegC static int32_t SensorOpsUpdateBitwise(struct SensorBusCfg *busCfg, struct SensorRegCfg *cfgItem) { + (void)busCfg; + (void)cfgItem; return HDF_SUCCESS; } @@ -114,13 +115,20 @@ static struct SensorOpsCall g_doOpsCall[] = { int32_t SetSensorRegCfgArray(struct SensorBusCfg *busCfg, const struct SensorRegCfgGroupNode *group) { int32_t num = 0; + uint32_t count; struct SensorRegCfg *cfgItem = NULL; CHECK_NULL_PTR_RETURN_VALUE(busCfg, HDF_FAILURE); CHECK_NULL_PTR_RETURN_VALUE(group, HDF_FAILURE); + CHECK_NULL_PTR_RETURN_VALUE(group->regCfgItem, HDF_FAILURE); + count = sizeof(g_doOpsCall) / sizeof(g_doOpsCall[0]); while (num < group->itemNum) { cfgItem = (group->regCfgItem + num); + if (cfgItem->opsType >= count) { + HDF_LOGE("%s: cfg item para invalid", __func__); + break; + } if (g_doOpsCall[cfgItem->opsType].ops != NULL) { if (g_doOpsCall[cfgItem->opsType].ops(busCfg, cfgItem) != HDF_SUCCESS) { HDF_LOGE("%s: malloc sensor reg config item data failed", __func__); diff --git a/model/sensor/driver/common/src/sensor_device_manager.c b/model/sensor/driver/common/src/sensor_device_manager.c index 94c3c950..e520262e 100644 --- a/model/sensor/driver/common/src/sensor_device_manager.c +++ b/model/sensor/driver/common/src/sensor_device_manager.c @@ -48,6 +48,10 @@ int32_t AddSensorDevice(const struct SensorDeviceInfo *deviceInfo) if (!existSensor) { devInfoNode = (struct SensorDevInfoNode*)OsalMemCalloc(sizeof(*devInfoNode)); + if (devInfoNode == NULL) { + (void)OsalMutexUnlock(&manager->mutex); + return HDF_FAILURE; + } if (memcpy_s(&devInfoNode->devInfo, sizeof(devInfoNode->devInfo), (void *)deviceInfo, sizeof(*deviceInfo)) != EOK) { HDF_LOGE("%s: copy sensor info failed", __func__); @@ -94,7 +98,10 @@ int32_t ReportSensorEvent(const struct SensorReportEvent *events) (void)OsalMutexLock(&manager->eventMutex); struct HdfSBuf *msg = HdfSBufObtain(HDF_SENSOR_EVENT_MAX_BUF); - CHECK_NULL_PTR_RETURN_VALUE(msg, HDF_ERR_INVALID_PARAM); + if (msg == NULL) { + (void)OsalMutexUnlock(&manager->eventMutex); + return HDF_ERR_INVALID_PARAM; + } if (!HdfSbufWriteBuffer(msg, events, sizeof(*events))) { HDF_LOGE("%s: sbuf write event failed", __func__); @@ -235,6 +242,7 @@ static int32_t DispatchCmdHandle(struct SensorDeviceInfo *deviceInfo, struct Hdf { int32_t methodCmd; int32_t loop; + int32_t count; CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); @@ -248,7 +256,8 @@ static int32_t DispatchCmdHandle(struct SensorDeviceInfo *deviceInfo, struct Hdf return HDF_FAILURE; } - for (loop = 0; loop < sizeof(g_sensorCmdHandle) / sizeof(g_sensorCmdHandle[0]); ++loop) { + count = sizeof(g_sensorCmdHandle) / sizeof(g_sensorCmdHandle[0]); + for (loop = 0; loop < count; ++loop) { if ((methodCmd == g_sensorCmdHandle[loop].cmd) && (g_sensorCmdHandle[loop].func != NULL)) { return g_sensorCmdHandle[loop].func(deviceInfo, data, reply); } @@ -310,15 +319,22 @@ int32_t InitSensorDevManager(struct HdfDeviceObject *device) CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_ERR_INVALID_PARAM); DListHeadInit(&manager->sensorDevInfoHead); - OsalMutexInit(&manager->mutex); - OsalMutexInit(&manager->eventMutex); + if (OsalMutexInit(&manager->mutex) != HDF_SUCCESS) { + HDF_LOGE("%s: init mutex failed", __func__); + return HDF_FAILURE; + } + + if (OsalMutexInit(&manager->eventMutex) != HDF_SUCCESS) { + HDF_LOGE("%s: init eventMutex failed", __func__); + return HDF_FAILURE; + } if (!HdfDeviceSetClass(device, DEVICE_CLASS_SENSOR)) { HDF_LOGE("%s: init sensor set class failed", __func__); return HDF_FAILURE; } - HDF_LOGI("%s: init sensor manager success", __func__); + HDF_LOGI("%s: init sensor manager successfully", __func__); return HDF_SUCCESS; } From 1856fee8f5af390769467e462c305d8d30e43d35 Mon Sep 17 00:00:00 2001 From: gonghui Date: Mon, 17 May 2021 16:07:59 +0800 Subject: [PATCH 04/21] sync L2 code to L1 --- ability/config/device_resource_if.c | 2 +- .../config/hcs_parser/include/hcs_blob_if.h | 4 +- .../hcs_parser/include/hcs_generate_tree.h | 6 +- .../config/hcs_parser/include/hcs_parser.h | 2 +- .../config/hcs_parser/include/hcs_tree_if.h | 2 +- ability/config/hcs_parser/src/hcs_blob_if.c | 6 +- .../config/hcs_parser/src/hcs_generate_tree.c | 10 +- ability/config/hcs_parser/src/hcs_parser.c | 6 +- ability/config/hcs_parser/src/hcs_tree_if.c | 30 +-- .../test/unittest/common/hdf_config_test.cpp | 176 +++++++++--------- 10 files changed, 120 insertions(+), 124 deletions(-) diff --git a/ability/config/device_resource_if.c b/ability/config/device_resource_if.c index 6bea6afd..5f75a409 100644 --- a/ability/config/device_resource_if.c +++ b/ability/config/device_resource_if.c @@ -41,7 +41,7 @@ static bool DeviceResourceIfaceConstruct(struct DeviceResourceIface *instance, D HcsIfaceConstruct(instance); break; default: - HDF_LOGE("%s: Currently, this configuration type is not supported. the type is %d", __func__, type); + HDF_LOGE("%s: Currently, this configuration type is not supported, the type is %d", __func__, type); return false; } return true; diff --git a/ability/config/hcs_parser/include/hcs_blob_if.h b/ability/config/hcs_parser/include/hcs_blob_if.h index b50c8f35..b2a73121 100644 --- a/ability/config/hcs_parser/include/hcs_blob_if.h +++ b/ability/config/hcs_parser/include/hcs_blob_if.h @@ -71,7 +71,7 @@ static inline uint32_t HcsGetPrefix(const char *start) #define HCS_PREFIX_LENGTH (HcsIsByteAlign() ? HCS_DWORD_LENGTH : 1) #define HCS_BYTE_LENGTH (HcsIsByteAlign() ? HCS_DWORD_LENGTH : 1) #define HCS_WORD_LENGTH (HcsIsByteAlign() ? HCS_DWORD_LENGTH : 2) -#define HCS_STRING_LENGTH(str) (HcsIsByteAlign() ? HcsAlignSize(strlen(str) + 1) : (strlen(str) + 1)) // add the '\0'. +#define HCS_STRING_LENGTH(str) (HcsIsByteAlign() ? HcsAlignSize(strlen(str) + 1) : (strlen(str) + 1)) int32_t HcsGetDataTypeOffset(const char *start); int32_t HcsGetAttrLength(const char *start); int32_t HcsGetNodeOrAttrLength(const char *start); @@ -82,4 +82,4 @@ bool HcsSwapToUint16(uint16_t *value, const char *realValue, uint32_t type); bool HcsSwapToUint32(uint32_t *value, const char *realValue, uint32_t type); bool HcsSwapToUint64(uint64_t *value, const char *realValue, uint32_t type); -#endif // HCS_BLOB_IF_H \ No newline at end of file +#endif /* HCS_BLOB_IF_H */ \ No newline at end of file diff --git a/ability/config/hcs_parser/include/hcs_generate_tree.h b/ability/config/hcs_parser/include/hcs_generate_tree.h index 2aa2c63e..d56bbcd7 100644 --- a/ability/config/hcs_parser/include/hcs_generate_tree.h +++ b/ability/config/hcs_parser/include/hcs_generate_tree.h @@ -13,9 +13,9 @@ #define TREE_STACK_MAX 64 struct TreeStack { - uint32_t offset; // the offset of node in blob - struct DeviceResourceNode *node; // the node is the head node of every layer tree + uint32_t offset; // The offset of the node in the blob. + struct DeviceResourceNode *node; // The head node of a layer tree. }; int32_t GenerateCfgTree(const char *treeStart, int32_t length, char *treeMem, struct DeviceResourceNode **root); -#endif // HCS_GENERATE_TREE_H \ No newline at end of file +#endif /* HCS_GENERATE_TREE_H */ \ No newline at end of file diff --git a/ability/config/hcs_parser/include/hcs_parser.h b/ability/config/hcs_parser/include/hcs_parser.h index 216eecc3..a20e26ba 100644 --- a/ability/config/hcs_parser/include/hcs_parser.h +++ b/ability/config/hcs_parser/include/hcs_parser.h @@ -13,4 +13,4 @@ bool HcsDecompile(const char *hcsBlob, uint32_t offset, struct DeviceResourceNode **root); -#endif // HCS_PARSER_H \ No newline at end of file +#endif /* HCS_PARSER_H */ \ No newline at end of file diff --git a/ability/config/hcs_parser/include/hcs_tree_if.h b/ability/config/hcs_parser/include/hcs_tree_if.h index b02bc332..09875dec 100644 --- a/ability/config/hcs_parser/include/hcs_tree_if.h +++ b/ability/config/hcs_parser/include/hcs_tree_if.h @@ -56,4 +56,4 @@ const struct DeviceResourceNode *HcsGetNodeByRefAttr(const struct DeviceResource #endif #endif /* __cplusplus */ -#endif // HCS_TREE_IF_H \ No newline at end of file +#endif /* HCS_TREE_IF_H */ \ No newline at end of file diff --git a/ability/config/hcs_parser/src/hcs_blob_if.c b/ability/config/hcs_parser/src/hcs_blob_if.c index 1f007c6f..dfb023d8 100644 --- a/ability/config/hcs_parser/src/hcs_blob_if.c +++ b/ability/config/hcs_parser/src/hcs_blob_if.c @@ -13,7 +13,7 @@ static bool g_byteAlign = false; -bool HcsIsByteAlign() +bool HcsIsByteAlign(void) { return g_byteAlign; } @@ -185,7 +185,7 @@ static bool CheckHcsBlobLength(uint32_t length, struct HbcHeader *header) HDF_LOGI("%s: the blobLength: %u, byteAlign: %d", __func__, blobLength, g_byteAlign); } if ((length != blobLength) || (blobLength < minLength)) { - HDF_LOGE("%s failed, Hcsblob file length is %u, But the length of calculation is %u", + HDF_LOGE("%s failed, Hcsblob file length is %u, but the calculated length is %u", __func__, length, blobLength); return false; } @@ -201,7 +201,7 @@ bool HcsCheckBlobFormat(const char *start, uint32_t length) } header = (struct HbcHeader *)start; if (header->magicNumber != HBC_MAGIC_NUMBER) { - HDF_LOGE("%s failed, the magic of HBC is %x", __func__, header->magicNumber); + HDF_LOGE("%s failed, the magic number of HBC is %x", __func__, header->magicNumber); return false; } if (!CheckHcsBlobLength(length, header)) { diff --git a/ability/config/hcs_parser/src/hcs_generate_tree.c b/ability/config/hcs_parser/src/hcs_generate_tree.c index cd638683..c3306ed6 100644 --- a/ability/config/hcs_parser/src/hcs_generate_tree.c +++ b/ability/config/hcs_parser/src/hcs_generate_tree.c @@ -53,7 +53,7 @@ static bool UpdateTreeStack(struct TreeStack **treeStack, int32_t *treeLayer, st uint32_t offset) { if (*treeLayer >= (TREE_STACK_MAX - 1)) { - HDF_LOGE("%s failed, the treeLayer error. treeLayer: %d", __func__, *treeLayer); + HDF_LOGE("%s failed, the treeLayer error, treeLayer: %d", __func__, *treeLayer); return false; } (*treeLayer)++; @@ -83,7 +83,7 @@ static int32_t ParseByteCode(const char *treeStart, int32_t offset, char **treeM { int32_t termOffset = HcsGetNodeOrAttrLength(treeStart + offset); if (termOffset <= 0) { - HDF_LOGE("%s failed, HcsGetNodeOrAttrLength failed, errno: %d", __func__, termOffset); + HDF_LOGE("%s failed, HcsGetNodeOrAttrLength error, errno: %d", __func__, termOffset); return HDF_FAILURE; } @@ -111,7 +111,7 @@ static int32_t ParseByteCode(const char *treeStart, int32_t offset, char **treeM } parentOrCurNode = GetParentNode(offset, *treeStack, treeLayerOrMemLen, termOffset); if (!AddAttrInNode(treeStart + offset, parentOrCurNode, treeMem)) { - HDF_LOGE("%s failed, the AddAttrInNode error", __func__); + HDF_LOGE("%s failed, AddAttrInNode error", __func__); return HDF_FAILURE; } break; @@ -136,14 +136,14 @@ int32_t GenerateCfgTree(const char *treeStart, int32_t length, char *treeMem, st while ((offset < length) && (offset >= 0)) { int32_t eachOffset = ParseByteCode(treeStart, offset, &treeMem, &treeStack, &treeLayerOrMemLen); if (eachOffset <= 0) { - HDF_LOGE("%s failed, the ParseByteCode error", __func__); + HDF_LOGE("%s failed, ParseByteCode error", __func__); treeLayerOrMemLen = eachOffset; break; } offset += eachOffset; } if ((treeMem != NULL) && (root != NULL) && (treeLayerOrMemLen > 0)) { - // the treeStack[1] is root + // The treeStack[1] is root *root = treeStack[1].node; } OsalMemFree(treeStack); diff --git a/ability/config/hcs_parser/src/hcs_parser.c b/ability/config/hcs_parser/src/hcs_parser.c index 50ef7643..29596bd5 100644 --- a/ability/config/hcs_parser/src/hcs_parser.c +++ b/ability/config/hcs_parser/src/hcs_parser.c @@ -23,19 +23,19 @@ bool HcsDecompile(const char *hcsBlob, uint32_t offset, struct DeviceResourceNod { int32_t nodeLength = HcsGetNodeLength(hcsBlob + offset); if (nodeLength < 0) { - HDF_LOGE("%s failed, HcsGetNodeLength failed", __func__); + HDF_LOGE("%s failed, HcsGetNodeLength error", __func__); return false; } int32_t treeMemLength = GetHcsTreeSize(hcsBlob + offset, nodeLength); if (treeMemLength <= 0) { - HDF_LOGE("%s failed, GetHcsTreeSize failed", __func__); + HDF_LOGE("%s failed, GetHcsTreeSize error, treeMemLength = %d", __func__, treeMemLength); return false; } char *treeMem = (char *)OsalMemCalloc(treeMemLength); if (treeMem == NULL) { - HDF_LOGE("%s failed, OsalMemCalloc Device tree memory failed", __func__); + HDF_LOGE("%s failed, OsalMemCalloc error", __func__); return false; } int32_t treeLayer = GenerateCfgTree(hcsBlob + offset, nodeLength, treeMem, root); diff --git a/ability/config/hcs_parser/src/hcs_tree_if.c b/ability/config/hcs_parser/src/hcs_tree_if.c index d4aba7c6..2b760a49 100644 --- a/ability/config/hcs_parser/src/hcs_tree_if.c +++ b/ability/config/hcs_parser/src/hcs_tree_if.c @@ -36,7 +36,7 @@ bool HcsGetBool(const struct DeviceResourceNode *node, const char *attrName) } if (!HcsSwapToUint8(&value, attr->value + HCS_PREFIX_LENGTH, HcsGetPrefix(attr->value))) { - HDF_LOGE("%s failed, Incorrect prefix code", __func__); + HDF_LOGE("%s failed, incorrect prefix", __func__); return false; } return value ? true : false; @@ -44,7 +44,7 @@ bool HcsGetBool(const struct DeviceResourceNode *node, const char *attrName) #define RETURN_DEFAULT_VALUE(attr, attrName, value, def) do { \ if (((attr) == NULL) || ((attr)->value == NULL) || ((value) == NULL)) { \ - HDF_LOGE("%s failed, the attr of %s is NULL, or the value is NULL, return the default value", \ + HDF_LOGE("%s failed, the attr of %s is NULL, or the value is NULL, the value is default value", \ __func__, ((attrName) == NULL) ? "error attrName" : (attrName)); \ if ((value) != NULL) { \ *(value) = (def); \ @@ -60,7 +60,7 @@ int32_t HcsGetUint8(const struct DeviceResourceNode *node, const char *attrName, if (!HcsSwapToUint8(value, attr->value + HCS_PREFIX_LENGTH, HcsGetPrefix(attr->value))) { *value = def; - HDF_LOGE("%s failed, Incorrect prefix code", __func__); + HDF_LOGE("%s failed, incorrect prefix", __func__); return HDF_FAILURE; } return HDF_SUCCESS; @@ -73,7 +73,7 @@ int32_t HcsGetUint16(const struct DeviceResourceNode *node, const char *attrName if (!HcsSwapToUint16(value, attr->value + HCS_PREFIX_LENGTH, HcsGetPrefix(attr->value))) { *value = def; - HDF_LOGE("%s failed, Incorrect prefix code", __func__); + HDF_LOGE("%s failed, incorrect prefix", __func__); return HDF_FAILURE; } return HDF_SUCCESS; @@ -86,7 +86,7 @@ int32_t HcsGetUint32(const struct DeviceResourceNode *node, const char *attrName if (!HcsSwapToUint32(value, attr->value + HCS_PREFIX_LENGTH, HcsGetPrefix(attr->value))) { *value = def; - HDF_LOGE("%s failed, Incorrect prefix code", __func__); + HDF_LOGE("%s failed, incorrect prefix", __func__); return HDF_FAILURE; } return HDF_SUCCESS; @@ -99,7 +99,7 @@ int32_t HcsGetUint64(const struct DeviceResourceNode *node, const char *attrName if (!HcsSwapToUint64(value, attr->value + HCS_PREFIX_LENGTH, HcsGetPrefix(attr->value))) { *value = def; - HDF_LOGE("%s failed, Incorrect prefix code", __func__); + HDF_LOGE("%s failed, incorrect prefix", __func__); return HDF_FAILURE; } return HDF_SUCCESS; @@ -116,7 +116,7 @@ static const char *GetArrayElem(const struct DeviceResourceAttr *attr, uint32_t return NULL; } if (index >= count) { - HDF_LOGE("%s failed, the index: %u >= count: %u", __func__, index, count); + HDF_LOGE("%s failed, index: %u >= count: %u", __func__, index, count); return NULL; } for (i = 0; i < index; i++) { @@ -144,7 +144,7 @@ int32_t HcsGetUint8ArrayElem(const struct DeviceResourceNode *node, const char * } if (!HcsSwapToUint8(value, realValue + HCS_PREFIX_LENGTH, HcsGetPrefix(realValue))) { *value = def; - HDF_LOGE("%s failed, Incorrect prefix code", __func__); + HDF_LOGE("%s failed, incorrect prefix", __func__); return HDF_ERR_INVALID_OBJECT; } return HDF_SUCCESS; @@ -165,7 +165,7 @@ int32_t HcsGetUint16ArrayElem(const struct DeviceResourceNode *node, const char } if (!HcsSwapToUint16(value, realValue + HCS_PREFIX_LENGTH, HcsGetPrefix(realValue))) { *value = def; - HDF_LOGE("%s failed, Incorrect prefix code", __func__); + HDF_LOGE("%s failed, incorrect prefix", __func__); return HDF_ERR_INVALID_OBJECT; } return HDF_SUCCESS; @@ -186,7 +186,7 @@ int32_t HcsGetUint32ArrayElem(const struct DeviceResourceNode *node, const char } if (!HcsSwapToUint32(value, realValue + HCS_PREFIX_LENGTH, HcsGetPrefix(realValue))) { *value = def; - HDF_LOGE("%s failed, Incorrect prefix code", __func__); + HDF_LOGE("%s failed, incorrect prefix", __func__); return HDF_ERR_INVALID_OBJECT; } return HDF_SUCCESS; @@ -202,7 +202,7 @@ int32_t HcsGetUint64ArrayElem(const struct DeviceResourceNode *node, const char realValue = GetArrayElem(attr, index); if ((realValue == NULL) || !HcsSwapToUint64(value, realValue + HCS_PREFIX_LENGTH, HcsGetPrefix(realValue))) { *value = def; - HDF_LOGE("%s failed, the realValue is NULL or incorrect prefix code", __func__); + HDF_LOGE("%s failed, invalid realValue (NULL) or incorrect prefix", __func__); return HDF_FAILURE; } return HDF_SUCCESS; @@ -211,11 +211,11 @@ int32_t HcsGetUint64ArrayElem(const struct DeviceResourceNode *node, const char #define CONTINUE_RETURN_DIFFERENT_ERRNO(ret, result) do { \ if ((result) == HDF_ERR_INVALID_OBJECT) { \ (ret) = HDF_ERR_INVALID_OBJECT; \ - HDF_LOGE("%s failed, the ret is %d", __func__, (result)); \ + HDF_LOGE("%s failed, the result is %d", __func__, (result)); \ continue; \ } \ if ((result) != HDF_SUCCESS) { \ - HDF_LOGE("%s failed, the ret is %d", __func__, (result)); \ + HDF_LOGE("%s failed, the result is %d", __func__, (result)); \ return result; \ } \ } while (0) @@ -316,7 +316,7 @@ int32_t HcsGetString(const struct DeviceResourceNode *node, const char *attrName RETURN_DEFAULT_VALUE(attr, attrName, value, def); if (HcsGetPrefix(attr->value) != CONFIG_STRING) { *value = def; - HDF_LOGE("%s failed, Incorrect prefix code", __func__); + HDF_LOGE("%s failed, incorrect prefix", __func__); return HDF_FAILURE; } *value = attr->value + HCS_PREFIX_LENGTH; @@ -366,7 +366,7 @@ const struct DeviceResourceNode *HcsGetNodeByMatchAttr(const struct DeviceResour const struct DeviceResourceNode *curNode = NULL; struct DeviceResourceIface *instance = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); if ((attrValue == NULL) || (instance == NULL) || (instance->GetRootNode == NULL)) { - HDF_LOGE("%s failed, attrValue is NULL or DeviceResourceGetIfaceInstance error", __func__); + HDF_LOGE("%s failed, attrValue or instance error", __func__); return NULL; } curNode = (node != NULL) ? node : instance->GetRootNode(); diff --git a/ability/config/test/unittest/common/hdf_config_test.cpp b/ability/config/test/unittest/common/hdf_config_test.cpp index 69c1800f..f8cd98cd 100644 --- a/ability/config/test/unittest/common/hdf_config_test.cpp +++ b/ability/config/test/unittest/common/hdf_config_test.cpp @@ -19,7 +19,7 @@ using namespace testing::ext; namespace ConfigTest { -const int8_t HDF_MSG_RESUL_DEFALUT = 3; +const int8_t HDF_MSG_RESULT_DEFAULT = 3; // hcs config test case number enum HdfTestCaseCmd { @@ -84,23 +84,19 @@ void HdfConfigTest::TearDownTestCase() HdfTestCloseService(); } -void HdfConfigTest::SetUp() -{ -} +void HdfConfigTest::SetUp() {} -void HdfConfigTest::TearDown() -{ -} +void HdfConfigTest::TearDown() {} /** * @tc.name: HslTestCreateDMHslToTree001 - * @tc.desc: Create a config tree, enter config test + * @tc.desc: Create a configuration tree and start configuration test * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestCreateDMHslToTree001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestCreateDMHslToTree001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_CREATE_DM_HSL_TO_TREE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_CREATE_DM_HSL_TO_TREE_001, HDF_MSG_RESULT_DEFAULT}; printf("HdfConfigTest enter\n\r"); EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -111,9 +107,9 @@ HWTEST_F(HdfConfigTest, HslTestCreateDMHslToTree001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetNodeByMatchAttrSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetNodeByMatchAttrSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_NODE_BY_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_NODE_BY_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -123,9 +119,9 @@ HWTEST_F(HdfConfigTest, HslTestGetNodeByMatchAttrSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetNodeByMatchAttrFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetNodeByMatchAttrFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_NODE_BY_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_NODE_BY_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -135,9 +131,9 @@ HWTEST_F(HdfConfigTest, HslTestGetNodeByMatchAttrFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetBoolAttrValueSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetBoolAttrValueSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_BOOL_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_BOOL_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -147,9 +143,9 @@ HWTEST_F(HdfConfigTest, HslTestGetBoolAttrValueSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetBoolAttrValueFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetBoolAttrValueFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_BOOL_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_BOOL_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -159,9 +155,9 @@ HWTEST_F(HdfConfigTest, HslTestGetBoolAttrValueFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint8AttrValueSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint8AttrValueSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -171,9 +167,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint8AttrValueSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint8AttrValueFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint8AttrValueFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -183,9 +179,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint8AttrValueFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint8ArrayElemSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint8ArrayElemSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ARRAY_ELEM_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ARRAY_ELEM_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -195,9 +191,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint8ArrayElemSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint8ArrayElemFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint8ArrayElemFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ARRAY_ELEM_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ARRAY_ELEM_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -207,9 +203,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint8ArrayElemFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint8ArraySuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint8ArraySuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ARRAY_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ARRAY_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -219,9 +215,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint8ArraySuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint8ArrayFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint8ArrayFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ARRAY_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT8_ARRAY_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -231,9 +227,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint8ArrayFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint16AttrValueSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint16AttrValueSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -243,9 +239,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint16AttrValueSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint16AttrValueFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint16AttrValueFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -255,9 +251,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint16AttrValueFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint16ArrayElemSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint16ArrayElemSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ARRAY_ELEM_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ARRAY_ELEM_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -268,9 +264,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint16ArrayElemSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint16ArrayElemFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint16ArrayElemFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ARRAY_ELEM_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ARRAY_ELEM_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -280,9 +276,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint16ArrayElemFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint16ArraySuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint16ArraySuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ARRAY_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ARRAY_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -292,9 +288,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint16ArraySuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint16ArrayFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint16ArrayFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ARRAY_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT16_ARRAY_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -304,9 +300,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint16ArrayFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint32AttrValueSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint32AttrValueSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -316,9 +312,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint32AttrValueSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint32AttrValueFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint32AttrValueFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -328,9 +324,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint32AttrValueFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint32ArrayElemSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint32ArrayElemSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ARRAY_ELEM_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ARRAY_ELEM_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -341,9 +337,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint32ArrayElemSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint32ArrayElemFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint32ArrayElemFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ARRAY_ELEM_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ARRAY_ELEM_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -353,9 +349,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint32ArrayElemFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint32ArraySuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint32ArraySuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ARRAY_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ARRAY_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -365,9 +361,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint32ArraySuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint32ArrayFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint32ArrayFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ARRAY_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT32_ARRAY_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -377,9 +373,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint32ArrayFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint64AttrValueSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint64AttrValueSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -389,9 +385,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint64AttrValueSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint64AttrValueFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint64AttrValueFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -401,9 +397,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint64AttrValueFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint64ArrayElemSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint64ArrayElemSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ARRAY_ELEM_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ARRAY_ELEM_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -414,9 +410,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint64ArrayElemSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint64ArrayElemFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint64ArrayElemFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ARRAY_ELEM_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ARRAY_ELEM_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -426,9 +422,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint64ArrayElemFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint64ArraySuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint64ArraySuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ARRAY_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ARRAY_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -438,9 +434,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint64ArraySuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetUint64ArrayFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetUint64ArrayFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ARRAY_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_UINT64_ARRAY_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -450,9 +446,9 @@ HWTEST_F(HdfConfigTest, HslTestGetUint64ArrayFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetElemNumSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetElemNumSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_ELEM_NUM_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_ELEM_NUM_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -462,9 +458,9 @@ HWTEST_F(HdfConfigTest, HslTestGetElemNumSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetElemNumFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetElemNumFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_ELEM_NUM_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_ELEM_NUM_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -474,9 +470,9 @@ HWTEST_F(HdfConfigTest, HslTestGetElemNumFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetChildNodeSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetChildNodeSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_CHILD_NODE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_CHILD_NODE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -486,9 +482,9 @@ HWTEST_F(HdfConfigTest, HslTestGetChildNodeSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetChildNodeFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetChildNodeFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_CHILD_NODE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_CHILD_NODE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -498,9 +494,9 @@ HWTEST_F(HdfConfigTest, HslTestGetChildNodeFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestTraverseAttrInNodeSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestTraverseAttrInNodeSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_TRAVERSE_ATTR_IN_NODE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_TRAVERSE_ATTR_IN_NODE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -510,9 +506,9 @@ HWTEST_F(HdfConfigTest, HslTestTraverseAttrInNodeSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestTraverseAttrInNodeFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestTraverseAttrInNodeFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_TRAVERSE_ATTR_IN_NODE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_TRAVERSE_ATTR_IN_NODE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -522,9 +518,9 @@ HWTEST_F(HdfConfigTest, HslTestTraverseAttrInNodeFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetStringSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetStringSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_STRING_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_STRING_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -534,9 +530,9 @@ HWTEST_F(HdfConfigTest, HslTestGetStringSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetStringFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetStringFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_STRING_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_STRING_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -546,9 +542,9 @@ HWTEST_F(HdfConfigTest, HslTestGetStringFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetStringArrayElemSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetStringArrayElemSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_STRING_ARRAY_ELEM_ATTR_VALUE_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_STRING_ARRAY_ELEM_ATTR_VALUE_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -559,9 +555,9 @@ HWTEST_F(HdfConfigTest, HslTestGetStringArrayElemSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetStringArrayElemFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetStringArrayElemFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_STRING_ARRAY_ELEM_ATTR_VALUE_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_STRING_ARRAY_ELEM_ATTR_VALUE_002, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -571,9 +567,9 @@ HWTEST_F(HdfConfigTest, HslTestGetStringArrayElemFail001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetNodeAttrRefSuccess001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetNodeAttrRefSuccess001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_NODE_BY_ATTR_REF_001, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_NODE_BY_ATTR_REF_001, HDF_MSG_RESULT_DEFAULT}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } @@ -583,9 +579,9 @@ HWTEST_F(HdfConfigTest, HslTestGetNodeAttrRefSuccess001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000DQ0TB */ -HWTEST_F(HdfConfigTest, HslTestGetNodeAttrRefFail001, TestSize.Level1) +HWTEST_F(HdfConfigTest, HslTestGetNodeAttrRefFail001, TestSize.Level0) { - struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_NODE_BY_ATTR_REF_002, HDF_MSG_RESUL_DEFALUT}; + struct HdfTestMsg msg = {TEST_CONFIG_TYPE, HDF_GET_NODE_BY_ATTR_REF_002, HDF_MSG_RESULT_DEFAULT}; printf("HdfConfigTest last enter\n\r"); EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } From 9bccf34cd63fc75b309b532d63ee9ebc76765e4f Mon Sep 17 00:00:00 2001 From: gonghui Date: Mon, 17 May 2021 16:35:06 +0800 Subject: [PATCH 05/21] sync L2 code to L1 code --- ability/sbuf/include/hdf_sbuf.h | 255 +++++++++++- ability/sbuf/include/hdf_sbuf_impl.h | 74 ++++ ability/sbuf/src/hdf_sbuf.c | 600 +++++++++++++-------------- ability/sbuf/src/hdf_sbuf_impl_raw.c | 553 ++++++++++++++++++++++++ 4 files changed, 1159 insertions(+), 323 deletions(-) create mode 100644 ability/sbuf/include/hdf_sbuf_impl.h create mode 100644 ability/sbuf/src/hdf_sbuf_impl_raw.c diff --git a/ability/sbuf/include/hdf_sbuf.h b/ability/sbuf/include/hdf_sbuf.h index 6fd3bd6c..1ec26e85 100644 --- a/ability/sbuf/include/hdf_sbuf.h +++ b/ability/sbuf/include/hdf_sbuf.h @@ -9,10 +9,11 @@ * @addtogroup Core * @{ * - * @brief Provides OpenHarmony Driver Foundation (HDF) APIs. + * @brief Provides functions to use the HarmonyOS Driver Foundation (HDF). * - * The HDF implements driver framework capabilities such as driver loading, service management, - * and driver message model. You can develop drivers based on the HDF. + * The HDF implements driver framework capabilities such as driver loading, service management, driver message model, + * and power management. + * You can develop drivers based on the HDF. * * @since 1.0 */ @@ -20,8 +21,8 @@ /** * @file hdf_sbuf.h * - * @brief Defines functions related to a HdfSBuf. The HDF provides data serialization and deserialization - * capabilities for data transmission between user-mode applications and kernel-mode drivers. + * @brief Declares functions related to the HDF SBUF. The HDF provides data serialization and deserialization + * capabilities for data transmission between user-space applications and kernel-space drivers. * * @since 1.0 */ @@ -33,19 +34,24 @@ #ifdef __cplusplus extern "C" { +#else +typedef uint16_t char16_t; #endif /* __cplusplus */ +struct HdfSBuf; +struct HdfSbufImpl; +struct HdfRemoteService; + /** - * @brief Defines a HdfSBuf. + * @brief Enumerates HDF SBUF types. * * @since 1.0 */ -struct HdfSBuf { - size_t writePos; /**< Current write position */ - size_t readPos; /**< Current read position */ - size_t capacity; /**< Storage capacity, at most 512 KB. */ - uint8_t *data; /**< Pointer to data storage */ - bool isBind; /**< Whether to bind the externally transferred pointer for data storage */ +enum HdfSbufType { + SBUF_RAW = 0, /* SBUF used for communication between the user space and the kernel space */ + SBUF_IPC, /* SBUF used for inter-process communication (IPC) */ + SBUF_IPC_HW, /* Reserved for extension */ + SBUF_TYPE_MAX, /* Maximum value of the SBUF type */ }; /** @@ -60,6 +66,18 @@ struct HdfSBuf { */ bool HdfSbufWriteBuffer(struct HdfSBuf *sbuf, const void *data, uint32_t writeSize); +/** + * @brief Writes unpadded data to a SBuf. You can call {@link HdfSbufReadUnpadBuffer} to read the unpadded data. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @param data Indicates the pointer to the data to write. The value cannot be a null pointer. + * @param writeSize Indicates the size of the data to write. The value cannot be 0. + * @return Returns true if the operation is successful; returns false otherwise. + * + * @since 1.0 + */ +bool HdfSbufWriteUnpadBuffer(struct HdfSBuf *sbuf, const uint8_t *data, uint32_t writeSize); + /** * @brief Writes a 64-bit unsigned integer to a SBuf. * @@ -159,13 +177,133 @@ bool HdfSbufWriteInt8(struct HdfSBuf *sbuf, int8_t value); */ bool HdfSbufWriteString(struct HdfSBuf *sbuf, const char *value); +/** + * @brief Writes a wide character string to a SBuf. + * The SBUF of the SBUF_RAW type does not support this function. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @param value Indicates the pointer to the wide character string to write. + * @param size Indicates the size of the wide character string to write. + * @return Returns true if the operation is successful; returns false otherwise. + * + * @since 1.0 + */ +bool HdfSbufWriteString16(struct HdfSBuf *sbuf, const char16_t *value, uint32_t size); + +/** + * @brief Writes a floating-point number to a SBuf. + * The SBUF of the SBUF_RAW type does not support this function. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @param value Indicates the floating-point number to write. + * @return Returns true if the operation is successful; returns false otherwise. + * + * @since 1.0 + */ +bool HdfSbufWriteFloat(struct HdfSBuf *sbuf, float value); + +/** + * @brief Writes a double-precision floating-point number to a SBuf. + * The SBUF of the SBUF_RAW type does not support this function. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @param value Indicates the double-precision floating-point number to write. + * @return Returns true if the operation is successful; returns false otherwise. + * + * @since 1.0 + */ +bool HdfSbufWriteDouble(struct HdfSBuf *sbuf, double value); + +/** + * @brief Writes a file descriptor to a SBuf. + * The SBUF of the SBUF_RAW type does not support this function. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @param fd Indicates the file descriptor to write. + * @return Returns true if the operation is successful; returns false otherwise. + * + * @since 1.0 + */ +bool HdfSbufWriteFileDescriptor(struct HdfSBuf *sbuf, int fd); + +/** + * @brief Writes an IPC service to a SBuf. The SBUF of the SBUF_RAW type does not support this function. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @param service Indicates the pointer to the IPC service to write. + * @return Returns 0 if the operation is successful; returns a negative value otherwise. + * + * @since 1.0 + */ +int32_t HdfSBufWriteRemoteService(struct HdfSBuf *sbuf, const struct HdfRemoteService *service); + +/** + * @brief Reads an IPC service from a SBuf. + * The SBUF of the SBUF_RAW type does not support this function. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @return Returns the pointer to the IPC service object if the operation is successful; + * returns a null pointer otherwise. + * + * @since 1.0 + */ +struct HdfRemoteService *HdfSBufReadRemoteService(struct HdfSBuf *sbuf); + +/** + * @brief Reads a file descriptor from a SBuf. + * The SBUF of the SBUF_RAW type does not support this function. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @return Returns a valid file descriptor if the operation is successful; returns a negative value otherwise. + * + * @since 1.0 + */ +int HdfSbufReadFileDescriptor(struct HdfSBuf *sbuf); + +/** + * @brief Reads a double-precision floating-point number from a SBuf. + * The SBUF of the SBUF_RAW type does not support this function. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @param value Indicates the pointer to the double-precision floating-point number read, + * which is requested by the caller. + * @return Returns true if the operation is successful; returns false otherwise. + * + * @since 1.0 + */ +bool HdfSbufReadDouble(struct HdfSBuf *sbuf, double *value); + +/** + * @brief Reads a floating-point number from a SBuf. + * The SBUF of the SBUF_RAW type does not support this function. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @param value Indicates the pointer to the floating-point number read, which is requested by the caller. + * @return Returns true if the operation is successful; returns false otherwise. + * + * @since 1.0 + */ +bool HdfSbufReadFloat(struct HdfSBuf *sbuf, float *value); + +/** + * @brief Reads a wide character string from a SBuf. + * The SBUF of the SBUF_RAW type does not support this function. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @return Returns the pointer to the wide character string if the operation is successful; + * returns a null pointer otherwise. + * + * @since 1.0 + */ +const char16_t *HdfSBufReadString16(struct HdfSBuf *sbuf); + /** * @brief Reads a data segment from a SBuf. * * @param sbuf Indicates the pointer to the target SBuf. * @param data Indicates the double pointer to the data read. The data read is stored in *data, - * which is requested by the caller. The memory pointed to by *data is managed by the SBuf - * and they share the same lifecycle. + * which is requested by the caller. The memory pointed to by *data is managed by + * the SBuf and they share the same lifecycle. * @param readSize Indicates the pointer to the size of the data read. * @return Returns true if the operation is successful; returns false otherwise. * @@ -173,6 +311,17 @@ bool HdfSbufWriteString(struct HdfSBuf *sbuf, const char *value); */ bool HdfSbufReadBuffer(struct HdfSBuf *sbuf, const void **data, uint32_t *readSize); +/** + * @brief Reads unpadded data from a SBuf. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @param length Indicates the length of the data to read. + * @return Returns the pointer to the unpadded data if the operation is successful; returns a null pointer otherwise. + * + * @since 1.0 + */ +const uint8_t *HdfSbufReadUnpadBuffer(struct HdfSBuf *sbuf, size_t length); + /** * @brief Reads a 64-bit unsigned integer from a SBuf. * @@ -273,10 +422,11 @@ bool HdfSbufReadInt8(struct HdfSBuf *sbuf, int8_t *value); const char *HdfSbufReadString(struct HdfSBuf *sbuf); /** - * @brief Obtains the pointer to the data stored in aSBuf. + * @brief Obtains the pointer to the data stored in a SBuf. * * @param sbuf Indicates the pointer to the target SBuf. - * @return Returns the pointer to the data stored in the target SBuf. + * @return Returns the pointer to the data stored in the target SBuf if the operation is successful; + * returns a null pointer otherwise. * * @since 1.0 */ @@ -296,6 +446,7 @@ void HdfSbufFlush(struct HdfSBuf *sbuf); * * @param sbuf Indicates the pointer to the target SBuf. * @return Returns the SBuf capacity. + * * @since 1.0 */ size_t HdfSbufGetCapacity(const struct HdfSBuf *sbuf); @@ -310,10 +461,20 @@ size_t HdfSbufGetCapacity(const struct HdfSBuf *sbuf); */ size_t HdfSbufGetDataSize(const struct HdfSBuf *sbuf); +/** + * @brief Sets the data size of a SBuf. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @param size Indicates the data size to set, which cannot exceed the size obtained via {@link HdfSbufGetDataSize}. + * + * @since 1.0 + */ +void HdfSbufSetDataSize(struct HdfSBuf *sbuf, size_t size); + /** * @brief Obtains a SBuf instance. * - * @param capacity Indicates the initial capacity of theSBuf. + * @param capacity Indicates the initial capacity of the SBuf. * @return Returns the SBuf instance. * * @since 1.0 @@ -343,9 +504,9 @@ struct HdfSBuf *HdfSBufObtainDefaultSize(void); struct HdfSBuf *HdfSBufBind(uintptr_t base, size_t size); /** - * @brief Releases a SBuf . + * @brief Releases a SBuf. * - * @param sbuf Indicates the pointer to the SBuf to release. + * @param sbuf Indicates the pointer to the target SBuf. * * @since 1.0 */ @@ -383,6 +544,62 @@ struct HdfSBuf *HdfSBufCopy(const struct HdfSBuf *sbuf); */ void HdfSbufTransDataOwnership(struct HdfSBuf *sbuf); +/** + * @brief Obtains a SBuf instance of a specified type. + * + * @param type Indicates the SBUF type, which is defined in {@link HdfSbufType}. + * @return Returns the SBuf instance. + * + * @since 1.0 + */ +struct HdfSBuf *HdfSBufTypedObtain(uint32_t type); + +/** + * @brief Obtains a SBuf instance of a specified type based on the implementation of an existing SBuf. + * + * @param type Indicates the SBUF type, which is defined in {@link HdfSbufType}. + * @param impl Indicates the pointer to the implementation of an existing SBuf. + * @return Returns the new SBuf instance. + * + * @since 1.0 + */ +struct HdfSBuf *HdfSBufTypedObtainInplace(uint32_t type, struct HdfSbufImpl *impl); + +/** + * @brief Obtains a SBuf instance of a specified type with the given initial capacity. + * + * @param type Indicates the SBUF type, which is defined in {@link HdfSbufType}. + * @param capacity Indicates the initial capacity of the SBuf. + * @return Returns the new SBuf instance. + * + * @since 1.0 + */ +struct HdfSBuf *HdfSBufTypedObtainCapacity(uint32_t type, size_t capacity); + +/** + * @brief Creates a SBuf instance of a specified type with the specified data and size. + * The pointer to the data stored in the SBuf is released by the caller, + * and the written data size should not exceed the specified value of size. + * + * @param type Indicates the SBUF type, which is defined in {@link HdfSbufType}. + * @param base Indicates the base of the data to use. + * @param size Indicates the size of the data to use. + * @return Returns the SBuf instance. + * + * @since 1.0 + */ +struct HdfSBuf *HdfSBufTypedBind(uint32_t type, uintptr_t base, size_t size); + +/** + * @brief Obtains the implementation of a SBuf. + * + * @param sbuf Indicates the pointer to the target SBuf. + * @return Returns the pointer to the implementation of the SBuf. + * + * @since 1.0 + */ +struct HdfSbufImpl *HdfSbufGetImpl(struct HdfSBuf *sbuf); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/ability/sbuf/include/hdf_sbuf_impl.h b/ability/sbuf/include/hdf_sbuf_impl.h new file mode 100644 index 00000000..4b7906ad --- /dev/null +++ b/ability/sbuf/include/hdf_sbuf_impl.h @@ -0,0 +1,74 @@ +/* + * 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_SBU_IMPL_H +#define HDF_SBU_IMPL_H + +#include "hdf_base.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct HdfSbufConstructor { + struct HdfSbufImpl *(*obtain)(size_t capacity); + struct HdfSbufImpl *(*bind)(uintptr_t base, size_t size); +}; + +struct HdfRemoteService; + +struct HdfSbufImpl { + bool (*writeBuffer)(struct HdfSbufImpl *sbuf, const uint8_t *data, uint32_t writeSize); + bool (*writeUnpadBuffer)(struct HdfSbufImpl *sbuf, const uint8_t *data, uint32_t writeSize); + bool (*writeUint64)(struct HdfSbufImpl *sbuf, uint64_t value); + bool (*writeUint32)(struct HdfSbufImpl *sbuf, uint32_t value); + bool (*writeUint16)(struct HdfSbufImpl *sbuf, uint16_t value); + bool (*writeUint8)(struct HdfSbufImpl *sbuf, uint8_t value); + bool (*writeInt64)(struct HdfSbufImpl *sbuf, int64_t value); + bool (*writeInt32)(struct HdfSbufImpl *sbuf, int32_t value); + bool (*writeInt16)(struct HdfSbufImpl *sbuf, int16_t value); + bool (*writeInt8)(struct HdfSbufImpl *sbuf, int8_t value); + bool (*writeString)(struct HdfSbufImpl *sbuf, const char *value); + bool (*writeFileDescriptor)(struct HdfSbufImpl *sbuf, int fd); + bool (*writeFloat)(struct HdfSbufImpl *sbuf, float value); + bool (*writeDouble)(struct HdfSbufImpl *sbuf, double value); + bool (*readDouble)(struct HdfSbufImpl *sbuf, double *value); + bool (*readFloat)(struct HdfSbufImpl *sbuf, float *value); + int (*readFileDescriptor)(struct HdfSbufImpl *sbuf); + bool (*writeString16)(struct HdfSbufImpl *sbuf, const char16_t *value, uint32_t size); + bool (*readBuffer)(struct HdfSbufImpl *sbuf, const uint8_t **data, uint32_t *readSize); + const uint8_t *(*readUnpadBuffer)(struct HdfSbufImpl *sbuf, size_t length); + bool (*readUint64)(struct HdfSbufImpl *sbuf, uint64_t *value); + bool (*readUint32)(struct HdfSbufImpl *sbuf, uint32_t *value); + bool (*readUint16)(struct HdfSbufImpl *sbuf, uint16_t *value); + bool (*readUint8)(struct HdfSbufImpl *sbuf, uint8_t *value); + bool (*readInt64)(struct HdfSbufImpl *sbuf, int64_t *value); + bool (*readInt32)(struct HdfSbufImpl *sbuf, int32_t *value); + bool (*readInt16)(struct HdfSbufImpl *sbuf, int16_t *value); + bool (*readInt8)(struct HdfSbufImpl *sbuf, int8_t *value); + const char *(*readString)(struct HdfSbufImpl *sbuf); + const char16_t *(*readString16)(struct HdfSbufImpl *sbuf); + int32_t (*writeRemoteService)(struct HdfSbufImpl *sbuf, const struct HdfRemoteService *service); + struct HdfRemoteService *(*readRemoteService)(struct HdfSbufImpl *sbuf); + const uint8_t *(*getData)(const struct HdfSbufImpl *sbuf); + void (*flush)(struct HdfSbufImpl *sbuf); + size_t (*getCapacity)(const struct HdfSbufImpl *sbuf); + size_t (*getDataSize)(const struct HdfSbufImpl *sbuf); + void (*setDataSize)(struct HdfSbufImpl *sbuf, size_t size); + void (*recycle)(struct HdfSbufImpl *sbuf); + struct HdfSbufImpl *(*move)(struct HdfSbufImpl *sbuf); + struct HdfSbufImpl *(*copy)(const struct HdfSbufImpl *sbuf); + void (*transDataOwnership)(struct HdfSbufImpl *sbuf); +}; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* HDF_SBUF_H */ +/** @} */ diff --git a/ability/sbuf/src/hdf_sbuf.c b/ability/sbuf/src/hdf_sbuf.c index 60341b0d..9aea25fc 100644 --- a/ability/sbuf/src/hdf_sbuf.c +++ b/ability/sbuf/src/hdf_sbuf.c @@ -6,459 +6,451 @@ * See the LICENSE file in the root of this repository for complete details. */ -#include "securec.h" -#include "osal_mem.h" -#include "hdf_log.h" #include "hdf_sbuf.h" +#include "hdf_log.h" +#include "hdf_sbuf_impl.h" +#include "osal_mem.h" -#define HDF_SBUF_GROW_SIZE_DEFAULT 256 -#define HDF_SBUF_MAX_SIZE (512 * 1024) // 512kB -#define HDF_SBUF_ALIGN 4 +#define HDF_SBUF_DEFAULT_SIZE 256 +#define HDF_SBUF_IMPL_CHECK_RETURN(sbuf, api, retCode) \ + do { \ + if (sbuf == NULL || sbuf->impl == NULL) { \ + HDF_LOGE("%s: invalid sbuf object", __func__); \ + return retCode; \ + } \ + if (sbuf->impl->api == NULL) { \ + HDF_LOGE(#api " is not support on %d sbuf", sbuf->type); \ + return retCode; \ + } \ + } while (0) -#ifndef INT16_MAX -#ifdef S16_MAX -#define INT16_MAX S16_MAX -#else -#define INT16_MAX 32767 -#endif // !S16_MAX -#endif // INT16_MAX +#define HDF_SBUF_IMPL_CHECK_RETURN_VOID(sbuf, api) \ + do { \ + if (sbuf == NULL || sbuf->impl == NULL) { \ + HDF_LOGE("%s: invalid sbuf object", __func__); \ + return; \ + } \ + if (sbuf->impl->api == NULL) { \ + HDF_LOGE(#api " is not support on %d sbuf", sbuf->type); \ + return; \ + } \ + } while (0) -static inline size_t HdfSbufGetAlignSize(size_t size) +struct HdfSBuf { + struct HdfSbufImpl *impl; + uint32_t type; +}; + +struct HdfSbufImpl *SbufObtainRaw(size_t capacity); +struct HdfSbufImpl *SbufBindRaw(uintptr_t base, size_t size); +struct HdfSbufImpl *SbufObtainIpc(size_t capacity) __attribute__((weak)); +struct HdfSbufImpl *SbufBindIpc(uintptr_t base, size_t size) __attribute__((weak)); +struct HdfSbufImpl *SbufObtainIpcHw(size_t capacity) __attribute__((weak)); +struct HdfSbufImpl *SbufBindRawIpcHw(uintptr_t base, size_t size) __attribute__((weak)); + +static const struct HdfSbufConstructor g_sbufConstructorMap[SBUF_TYPE_MAX] = { + [SBUF_RAW] = { + .obtain = SbufObtainRaw, + .bind = SbufBindRaw, + }, + [SBUF_IPC] = { + .obtain = SbufObtainIpc, + .bind = SbufBindIpc, + }, + [SBUF_IPC_HW] = { + .obtain = SbufObtainIpcHw, + .bind = SbufBindRawIpcHw, + }, +}; + +static const struct HdfSbufConstructor *HdfSbufConstructorGet(uint32_t type) { - return (size + HDF_SBUF_ALIGN - 1) & (~(HDF_SBUF_ALIGN - 1)); -} - -static size_t HdfSbufGetLeftWriteSize(struct HdfSBuf *sbuf) -{ - return (sbuf->capacity < sbuf->writePos) ? 0 : (sbuf->capacity - sbuf->writePos); -} - -static size_t HdfSbufGetLeftReadSize(struct HdfSBuf *sbuf) -{ - return (sbuf->writePos < sbuf->readPos) ? 0 : (sbuf->writePos - sbuf->readPos); -} - -static bool HdfSbufWriteRollback(struct HdfSBuf *sbuf, uint32_t size) -{ - size_t alignSize = HdfSbufGetAlignSize(size); - if (sbuf->writePos < alignSize) { - return false; + if (type >= SBUF_TYPE_MAX) { + return NULL; } - sbuf->writePos -= alignSize; - return true; -} - -static bool HdfSbufReadRollback(struct HdfSBuf *sbuf, uint32_t size) -{ - size_t alignSize = HdfSbufGetAlignSize(size); - if (sbuf->readPos < alignSize) { - return false; - } - - sbuf->readPos -= alignSize; - return true; + return &g_sbufConstructorMap[type]; } uint8_t *HdfSbufGetData(const struct HdfSBuf *sbuf) { - if (sbuf == NULL) { - HDF_LOGE("Get data is null, input sbuf is null"); - return NULL; - } - return (uint8_t *)sbuf->data; + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, getData, NULL); + return (uint8_t *)sbuf->impl->getData(sbuf->impl); } void HdfSbufFlush(struct HdfSBuf *sbuf) { - if (sbuf != NULL) { - sbuf->readPos = 0; - sbuf->writePos = 0; - } + HDF_SBUF_IMPL_CHECK_RETURN_VOID(sbuf, getData); + sbuf->impl->flush(sbuf->impl); } size_t HdfSbufGetCapacity(const struct HdfSBuf *sbuf) { - return (sbuf != NULL) ? sbuf->capacity : 0; + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, getCapacity, HDF_FAILURE); + return (sbuf != NULL && sbuf->impl != NULL) ? sbuf->impl->getCapacity(sbuf->impl) : 0; } size_t HdfSbufGetDataSize(const struct HdfSBuf *sbuf) { - return (sbuf != NULL) ? sbuf->writePos : 0; + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, getDataSize, HDF_FAILURE); + return sbuf->impl->getDataSize(sbuf->impl); } -static bool HdfSbufGrow(struct HdfSBuf *sbuf, uint32_t growSize) +void HdfSbufSetDataSize(struct HdfSBuf *sbuf, size_t size) { - if (sbuf->isBind) { - HDF_LOGE("%s: binded sbuf oom", __func__); - return false; - } - - uint32_t newSize = HdfSbufGetAlignSize(sbuf->capacity + growSize); - if (newSize < sbuf->capacity) { - HDF_LOGE("%s: grow size overflow", __func__); - return false; - } - if (newSize > HDF_SBUF_MAX_SIZE) { - HDF_LOGE("%s: buf size over limit", __func__); - return false; - } - - uint8_t *newData = OsalMemCalloc(newSize); - if (newData == NULL) { - HDF_LOGE("%s: oom", __func__); - return false; - } - - if (sbuf->data != NULL) { - if (memcpy_s(newData, newSize, sbuf->data, sbuf->writePos) != EOK) { - OsalMemFree(newData); - return false; - } - OsalMemFree(sbuf->data); - } - - sbuf->data = newData; - sbuf->capacity = newSize; - - return true; -} - -static bool HdfSbufWrite(struct HdfSBuf *sbuf, const uint8_t *data, uint32_t size) -{ - if (sbuf == NULL || sbuf->data == NULL || data == NULL) { - return false; - } - - if (size == 0) { - return true; - } - - size_t alignSize = HdfSbufGetAlignSize(size); - // in case of desireCapacity overflow - if (alignSize < size) { - HDF_LOGE("desireCapacity is overflow"); - return false; - } - size_t writeableSize = HdfSbufGetLeftWriteSize(sbuf); - if (alignSize > writeableSize) { - size_t growSize = (alignSize > HDF_SBUF_GROW_SIZE_DEFAULT) ? (alignSize + HDF_SBUF_GROW_SIZE_DEFAULT) : - HDF_SBUF_GROW_SIZE_DEFAULT; - if (!HdfSbufGrow(sbuf, growSize)) { - return false; - } - writeableSize = HdfSbufGetLeftWriteSize(sbuf); - } - - uint8_t *dest = sbuf->data + sbuf->writePos; - if (memcpy_s(dest, writeableSize, data, size) != EOK) { - return false; /* never hits */ - } - - sbuf->writePos += alignSize; - return true; -} - -static bool HdfSbufRead(struct HdfSBuf *sbuf, uint8_t *data, uint32_t readSize) -{ - if (sbuf == NULL || sbuf->data == NULL || data == NULL) { - return false; - } - - if (readSize == 0) { - return true; - } - - size_t alignSize = HdfSbufGetAlignSize(readSize); - if (alignSize > HdfSbufGetLeftReadSize(sbuf)) { - HDF_LOGE("Read out of buffer range"); - return false; - } - - if (memcpy_s(data, readSize, sbuf->data + sbuf->readPos, readSize) != EOK) { - return false; // never hits - } - sbuf->readPos += alignSize; - return true; + HDF_SBUF_IMPL_CHECK_RETURN_VOID(sbuf, setDataSize); + sbuf->impl->setDataSize(sbuf->impl, size); } bool HdfSbufWriteBuffer(struct HdfSBuf *sbuf, const void *data, uint32_t writeSize) { - if (sbuf == NULL) { - HDF_LOGE("Write buffer failed, input param is invalid"); - return false; - } + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, getCapacity, false); + return sbuf->impl->writeBuffer(sbuf->impl, (const uint8_t *)data, writeSize); +} + +bool HdfSbufWriteUnpadBuffer(struct HdfSBuf *sbuf, const uint8_t *data, uint32_t writeSize) +{ if (data == NULL) { - return HdfSbufWriteInt32(sbuf, 0); - } - - if (!HdfSbufWriteInt32(sbuf, writeSize)) { - return false; - } - if (!HdfSbufWrite(sbuf, data, writeSize)) { - (void)HdfSbufWriteRollback(sbuf, sizeof(int32_t)); return false; } - return true; + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeUnpadBuffer, false); + return sbuf->impl->writeUnpadBuffer(sbuf->impl, data, writeSize); +} + +const uint8_t *HdfSbufReadUnpadBuffer(struct HdfSBuf *sbuf, size_t length) +{ + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readUnpadBuffer, false); + return sbuf->impl->readUnpadBuffer(sbuf->impl, length); } bool HdfSbufReadBuffer(struct HdfSBuf *sbuf, const void **data, uint32_t *readSize) { - if (sbuf == NULL || sbuf->data == NULL || data == NULL || readSize == NULL) { - HDF_LOGE("%s:input invalid", __func__); - return false; - } - - int buffSize = 0; - if (!HdfSbufReadInt32(sbuf, &buffSize)) { - return false; - } - - if (buffSize == 0) { - *data = NULL; - *readSize = 0; - return true; - } - size_t alignSize = HdfSbufGetAlignSize(buffSize); - if (alignSize > HdfSbufGetLeftReadSize(sbuf)) { - HDF_LOGE("%s:readBuff out of range", __func__); - (void)HdfSbufReadRollback(sbuf, sizeof(int32_t)); - return false; - } - - *data = sbuf->data + sbuf->readPos; - *readSize = buffSize; - sbuf->readPos += alignSize; - return true; + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readBuffer, false); + return sbuf->impl->readBuffer(sbuf->impl, (const uint8_t **)data, readSize); } bool HdfSbufWriteUint64(struct HdfSBuf *sbuf, uint64_t value) { - return HdfSbufWrite(sbuf, (uint8_t *)(&value), sizeof(value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeUint64, false); + return sbuf->impl->writeUint64(sbuf->impl, value); } bool HdfSbufWriteUint32(struct HdfSBuf *sbuf, uint32_t value) { - return HdfSbufWrite(sbuf, (uint8_t *)(&value), sizeof(value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeUint32, false); + return sbuf->impl->writeUint32(sbuf->impl, value); } bool HdfSbufWriteUint16(struct HdfSBuf *sbuf, uint16_t value) { - return HdfSbufWrite(sbuf, (uint8_t *)(&value), sizeof(value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeUint16, false); + return sbuf->impl->writeUint16(sbuf->impl, value); } bool HdfSbufWriteUint8(struct HdfSBuf *sbuf, uint8_t value) { - return HdfSbufWrite(sbuf, (uint8_t *)(&value), sizeof(value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeUint8, false); + return sbuf->impl->writeUint8(sbuf->impl, value); } bool HdfSbufWriteInt64(struct HdfSBuf *sbuf, int64_t value) { - return HdfSbufWrite(sbuf, (uint8_t *)(&value), sizeof(value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeInt64, false); + return sbuf->impl->writeInt64(sbuf->impl, value); } bool HdfSbufWriteInt32(struct HdfSBuf *sbuf, int32_t value) { - return HdfSbufWrite(sbuf, (uint8_t *)(&value), sizeof(value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeInt32, false); + return sbuf->impl->writeInt32(sbuf->impl, value); } bool HdfSbufWriteInt16(struct HdfSBuf *sbuf, int16_t value) { - return HdfSbufWrite(sbuf, (uint8_t *)(&value), sizeof(value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeInt16, false); + return sbuf->impl->writeInt16(sbuf->impl, value); } bool HdfSbufWriteInt8(struct HdfSBuf *sbuf, int8_t value) { - return HdfSbufWrite(sbuf, (uint8_t *)(&value), sizeof(value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeInt8, false); + return sbuf->impl->writeInt8(sbuf->impl, value); } bool HdfSbufWriteString(struct HdfSBuf *sbuf, const char *value) { - if (sbuf == NULL) { - HDF_LOGE("%s:input null", __func__); - return false; - } + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeString, false); + return sbuf->impl->writeString(sbuf->impl, value); +} - return HdfSbufWriteBuffer(sbuf, value, value ? (strlen(value) + 1) : 0); +bool HdfSbufWriteString16(struct HdfSBuf *sbuf, const char16_t *value, uint32_t size) +{ + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeString16, false); + return sbuf->impl->writeString16(sbuf->impl, value, size); } bool HdfSbufReadUint64(struct HdfSBuf *sbuf, uint64_t *value) { - return HdfSbufRead(sbuf, (uint8_t *)(value), sizeof(*value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readUint64, false); + return sbuf->impl->readUint64(sbuf->impl, value); } bool HdfSbufReadUint32(struct HdfSBuf *sbuf, uint32_t *value) { - return HdfSbufRead(sbuf, (uint8_t *)(value), sizeof(*value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readUint32, false); + return sbuf->impl->readUint32(sbuf->impl, value); } bool HdfSbufReadUint16(struct HdfSBuf *sbuf, uint16_t *value) { - return HdfSbufRead(sbuf, (uint8_t *)(value), sizeof(*value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readUint16, false); + return sbuf->impl->readUint16(sbuf->impl, value); } bool HdfSbufReadUint8(struct HdfSBuf *sbuf, uint8_t *value) { - return HdfSbufRead(sbuf, (uint8_t *)(value), sizeof(*value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readUint8, false); + return sbuf->impl->readUint8(sbuf->impl, value); } bool HdfSbufReadInt64(struct HdfSBuf *sbuf, int64_t *value) { - return HdfSbufRead(sbuf, (uint8_t *)(value), sizeof(*value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readInt64, false); + return sbuf->impl->readInt64(sbuf->impl, value); } bool HdfSbufReadInt32(struct HdfSBuf *sbuf, int32_t *value) { - return HdfSbufRead(sbuf, (uint8_t *)(value), sizeof(*value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readInt32, false); + return sbuf->impl->readInt32(sbuf->impl, value); } bool HdfSbufReadInt16(struct HdfSBuf *sbuf, int16_t *value) { - return HdfSbufRead(sbuf, (uint8_t *)(value), sizeof(*value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readInt16, false); + return sbuf->impl->readInt16(sbuf->impl, value); } bool HdfSbufReadInt8(struct HdfSBuf *sbuf, int8_t *value) { - return HdfSbufRead(sbuf, (uint8_t *)(value), sizeof(*value)); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readInt8, false); + return sbuf->impl->readInt8(sbuf->impl, value); } const char *HdfSbufReadString(struct HdfSBuf *sbuf) { - if (sbuf == NULL || sbuf->data == NULL) { - HDF_LOGE("%s:input null", __func__); - return NULL; - } - /* this length contains '\0' at the end. */ - int32_t strLen = 0; - if (!HdfSbufReadInt32(sbuf, &strLen) || strLen <= 0) { - return NULL; - } - size_t alignSize = HdfSbufGetAlignSize(strLen); - if (strLen > INT16_MAX || alignSize > HdfSbufGetLeftReadSize(sbuf)) { - (void)HdfSbufReadRollback(sbuf, sizeof(int32_t)); - return NULL; - } - - char *str = (char *)(sbuf->data + sbuf->readPos); - sbuf->readPos += alignSize; - /* force set '\0' at end of the string */ - str[strLen - 1] = '\0'; - return str; + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readString, false); + return sbuf->impl->readString(sbuf->impl); } -struct HdfSBuf *HdfSBufObtainDefaultSize() +bool HdfSBufWriteString16(struct HdfSBuf *sbuf, const char16_t *value, uint32_t size) { - return HdfSBufObtain(HDF_SBUF_GROW_SIZE_DEFAULT); + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeString16, false); + return sbuf->impl->writeString16(sbuf->impl, value, size); +} + +const char16_t *HdfSBufReadString16(struct HdfSBuf *sbuf) +{ + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readString16, false); + return sbuf->impl->readString16(sbuf->impl); +} + +int32_t HdfSBufWriteRemoteService(struct HdfSBuf *sbuf, const struct HdfRemoteService *service) +{ + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeRemoteService, false); + return sbuf->impl->writeRemoteService(sbuf->impl, service); +} + +struct HdfRemoteService *HdfSBufReadRemoteService(struct HdfSBuf *sbuf) +{ + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readRemoteService, false); + return sbuf->impl->readRemoteService(sbuf->impl); +} + +bool HdfSbufWriteFloat(struct HdfSBuf *sbuf, float data) +{ + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeFloat, false); + return sbuf->impl->writeFloat(sbuf->impl, data); +} + +bool HdfSbufWriteDouble(struct HdfSBuf *sbuf, double data) +{ + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeDouble, false); + return sbuf->impl->writeDouble(sbuf->impl, data); +} + +bool HdfSbufWriteFileDescriptor(struct HdfSBuf *sbuf, int fd) +{ + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, writeFileDescriptor, false); + return sbuf->impl->writeFileDescriptor(sbuf->impl, fd); +} + +int HdfSbufReadFileDescriptor(struct HdfSBuf *sbuf) +{ + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readFileDescriptor, false); + return sbuf->impl->readFileDescriptor(sbuf->impl); +} + +bool HdfSbufReadDouble(struct HdfSBuf *sbuf, double *data) +{ + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readDouble, false); + return sbuf->impl->readDouble(sbuf->impl, data); +} + +bool HdfSbufReadFloat(struct HdfSBuf *sbuf, float *data) +{ + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, readFloat, false); + return sbuf->impl->readFloat(sbuf->impl, data); +} + +struct HdfSBuf *HdfSBufTypedObtainCapacity(uint32_t type, size_t capacity) +{ + const struct HdfSbufConstructor *constructor = HdfSbufConstructorGet(type); + if (constructor == NULL) { + HDF_LOGE("sbuf constructor %d not implement", type); + return NULL; + } + if (constructor->obtain == NULL) { + HDF_LOGE("sbuf constructor %d obtain method not implement", type); + return NULL; + } + + struct HdfSBuf *sbuf = (struct HdfSBuf *)OsalMemAlloc(sizeof(struct HdfSBuf)); + if (sbuf == NULL) { + HDF_LOGE("instance sbuf failure"); + return NULL; + } + + sbuf->impl = constructor->obtain(capacity); + if (sbuf->impl == NULL) { + OsalMemFree(sbuf); + HDF_LOGE("sbuf obtain fail, size=%u", (uint32_t)capacity); + return NULL; + } + sbuf->type = type; + return sbuf; +} + +struct HdfSBuf *HdfSBufTypedObtainInplace(uint32_t type, struct HdfSbufImpl *impl) +{ + if (type >= SBUF_TYPE_MAX || impl == NULL) { + return NULL; + } + + struct HdfSBuf *sbuf = (struct HdfSBuf *)OsalMemAlloc(sizeof(struct HdfSBuf)); + if (sbuf == NULL) { + HDF_LOGE("obtain in-place sbuf failure"); + return NULL; + } + + sbuf->impl = impl; + sbuf->type = type; + return sbuf; +} + +struct HdfSBuf *HdfSBufTypedObtain(uint32_t type) +{ + return HdfSBufTypedObtainCapacity(type, HDF_SBUF_DEFAULT_SIZE); +} + +struct HdfSBuf *HdfSBufTypedBind(uint32_t type, uintptr_t base, size_t size) +{ + const struct HdfSbufConstructor *constructor = HdfSbufConstructorGet(type); + if (constructor == NULL) { + HDF_LOGE("sbuf constructor %d not implement", type); + return NULL; + } + + if (constructor->bind == NULL) { + HDF_LOGE("sbuf constructor %d bind method not implement", type); + return NULL; + } + + struct HdfSBuf *sbuf = (struct HdfSBuf *)OsalMemAlloc(sizeof(struct HdfSBuf)); + if (sbuf == NULL) { + HDF_LOGE("instance sbuf failure"); + return NULL; + } + + sbuf->impl = constructor->bind(base, size); + if (sbuf->impl == NULL) { + OsalMemFree(sbuf); + HDF_LOGE("sbuf bind fail"); + return NULL; + } + sbuf->type = type; + return sbuf; } struct HdfSBuf *HdfSBufObtain(size_t capacity) { - if (capacity > HDF_SBUF_MAX_SIZE) { - HDF_LOGE("%s: buf size over limit", __func__); - return NULL; - } - struct HdfSBuf *sbuf = (struct HdfSBuf *)OsalMemAlloc(sizeof(struct HdfSBuf)); - if (sbuf == NULL) { - HDF_LOGE("instance usbuf failure"); - return NULL; - } + return HdfSBufTypedObtainCapacity(SBUF_RAW, capacity); +} - sbuf->data = (uint8_t *)OsalMemCalloc(capacity); - if (sbuf->data == NULL) { - OsalMemFree(sbuf); - HDF_LOGE("sbuf obtain oom, size=%u", (uint32_t)capacity); - return NULL; - } - sbuf->capacity = capacity; - sbuf->writePos = 0; - sbuf->readPos = 0; - sbuf->isBind = false; - return sbuf; +struct HdfSBuf *HdfSBufObtainDefaultSize() +{ + return HdfSBufObtain(HDF_SBUF_DEFAULT_SIZE); } struct HdfSBuf *HdfSBufBind(uintptr_t base, size_t size) { - if (base == 0 || size == 0) { - return NULL; - } - /* require 4 byte alignment for base */ - if ((base & 0x3) != 0) { - HDF_LOGE("Base is not align for 4-byte"); - return NULL; - } - struct HdfSBuf *sbuf = (struct HdfSBuf *)OsalMemAlloc(sizeof(struct HdfSBuf)); - if (sbuf == NULL) { - HDF_LOGE("%s: oom", __func__); - return NULL; - } - - sbuf->data = (uint8_t *)base; - sbuf->capacity = size; - sbuf->writePos = size; - sbuf->readPos = 0; - sbuf->isBind = true; - return sbuf; + return HdfSBufTypedBind(SBUF_RAW, base, size); } struct HdfSBuf *HdfSBufCopy(const struct HdfSBuf *sbuf) { - if (sbuf == NULL || sbuf->data == NULL) { + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, copy, NULL); + struct HdfSBuf *newBuf = (struct HdfSBuf *)OsalMemAlloc(sizeof(struct HdfSBuf)); + if (newBuf == NULL) { return NULL; } - - struct HdfSBuf *new = HdfSBufObtain(sbuf->capacity); - if (new == NULL) { + newBuf->impl = sbuf->impl->copy(sbuf->impl); + if (newBuf->impl == NULL) { + OsalMemFree(newBuf); return NULL; } - new->capacity = sbuf->capacity; - new->readPos = 0; - new->writePos = sbuf->writePos; - if (memcpy_s(new->data, new->capacity, sbuf->data, sbuf->writePos) != EOK) { - HdfSBufRecycle(new); - return NULL; - } - - return new; + newBuf->type = sbuf->type; + return newBuf; } struct HdfSBuf *HdfSBufMove(struct HdfSBuf *sbuf) { - if (sbuf == NULL || sbuf->isBind) { + HDF_SBUF_IMPL_CHECK_RETURN(sbuf, move, NULL); + struct HdfSBuf *newBuf = (struct HdfSBuf *)OsalMemAlloc(sizeof(struct HdfSBuf)); + if (newBuf == NULL) { return NULL; } - - struct HdfSBuf *new = OsalMemCalloc(sizeof(struct HdfSBuf)); - if (new == NULL) { + newBuf->impl = sbuf->impl->move(sbuf->impl); + if (newBuf->impl == NULL) { + OsalMemFree(newBuf); return NULL; } - new->capacity = sbuf->capacity; - new->readPos = 0; - new->writePos = sbuf->writePos; - new->data = sbuf->data; - - sbuf->data = NULL; - sbuf->capacity = 0; - HdfSbufFlush(sbuf); - - return new; + return newBuf; } void HdfSbufTransDataOwnership(struct HdfSBuf *sbuf) { - if (sbuf == NULL) { - return; - } - - sbuf->isBind = false; + HDF_SBUF_IMPL_CHECK_RETURN_VOID(sbuf, transDataOwnership); + sbuf->impl->transDataOwnership(sbuf->impl); } void HdfSBufRecycle(struct HdfSBuf *sbuf) { if (sbuf != NULL) { - if (sbuf->data != NULL && !sbuf->isBind) { - OsalMemFree(sbuf->data); + if (sbuf->impl != NULL && sbuf->impl->recycle != NULL) { + sbuf->impl->recycle(sbuf->impl); + sbuf->impl = NULL; } OsalMemFree(sbuf); } } + +struct HdfSbufImpl *HdfSbufGetImpl(struct HdfSBuf *sbuf) +{ + if (sbuf != NULL) { + return sbuf->impl; + } + + return NULL; +} \ No newline at end of file diff --git a/ability/sbuf/src/hdf_sbuf_impl_raw.c b/ability/sbuf/src/hdf_sbuf_impl_raw.c new file mode 100644 index 00000000..051eacb4 --- /dev/null +++ b/ability/sbuf/src/hdf_sbuf_impl_raw.c @@ -0,0 +1,553 @@ +/* + * 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_log.h" +#include "hdf_sbuf.h" +#include "hdf_sbuf_impl.h" +#include "osal_mem.h" +#include "securec.h" + +#define HDF_SBUF_GROW_SIZE_DEFAULT 256 +#define HDF_SBUF_MAX_SIZE (512 * 1024) // 512KB +#define HDF_SBUF_ALIGN 4 + +#ifndef INT16_MAX +#ifdef S16_MAX +#define INT16_MAX S16_MAX +#else +#define INT16_MAX 32767 +#endif // !S16_MAX +#endif // INT16_MAX + +struct HdfSBufRaw { + struct HdfSbufImpl infImpl; + size_t writePos; /**< Current write position */ + size_t readPos; /**< Current read position */ + size_t capacity; /**< Storage capacity, 512 KB at most. */ + uint8_t *data; /**< Pointer to data storage */ + bool isBind; /**< Whether to bind the externally transferred pointer to data storage */ +}; + +#define SBUF_RAW_CAST(impl) (struct HdfSBufRaw *)(impl) + +static struct HdfSBufRaw *SbufRawImplNewInstance(size_t capacity); +static void SbufInterfaceAssign(struct HdfSbufImpl *inf); + +static size_t SbufRawImplGetAlignSize(size_t size) +{ + return (size + HDF_SBUF_ALIGN - 1) & (~(HDF_SBUF_ALIGN - 1)); +} + +static void SbufRawImplRecycle(struct HdfSbufImpl *impl) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf != NULL) { + if (sbuf->data != NULL && !sbuf->isBind) { + OsalMemFree(sbuf->data); + } + OsalMemFree(sbuf); + } +} + +static size_t SbufRawImplGetLeftWriteSize(struct HdfSBufRaw *sbuf) +{ + return (sbuf->capacity < sbuf->writePos) ? 0 : (sbuf->capacity - sbuf->writePos); +} + +static size_t SbufRawImplGetLeftReadSize(struct HdfSBufRaw *sbuf) +{ + return (sbuf->writePos < sbuf->readPos) ? 0 : (sbuf->writePos - sbuf->readPos); +} + +static bool SbufRawImplWriteRollback(struct HdfSbufImpl *impl, uint32_t size) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf == NULL) { + return false; + } + + size_t alignSize = SbufRawImplGetAlignSize(size); + if (sbuf->writePos < alignSize) { + return false; + } + + sbuf->writePos -= alignSize; + return true; +} + +static bool SbufRawImplReadRollback(struct HdfSbufImpl *impl, uint32_t size) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf == NULL) { + return false; + } + + size_t alignSize = SbufRawImplGetAlignSize(size); + if (sbuf->readPos < alignSize) { + return false; + } + + sbuf->readPos -= alignSize; + return true; +} + +static const uint8_t *SbufRawImplGetData(const struct HdfSbufImpl *impl) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf == NULL) { + HDF_LOGE("The obtained data is null, and the input Sbuf is null."); + return NULL; + } + return (uint8_t *)sbuf->data; +} + +static void SbufRawImplSetDataSize(struct HdfSbufImpl *impl, size_t size) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf == NULL) { + return; + } + if (size <= sbuf->capacity) { + sbuf->readPos = 0; + sbuf->writePos = size; + } +} + +static void SbufRawImplFlush(struct HdfSbufImpl *impl) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf != NULL) { + sbuf->readPos = 0; + sbuf->writePos = 0; + } +} + +static size_t SbufRawImplGetCapacity(const struct HdfSbufImpl *impl) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + return (sbuf != NULL) ? sbuf->capacity : 0; +} + +static size_t SbufRawImplGetDataSize(const struct HdfSbufImpl *impl) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + return (sbuf != NULL) ? sbuf->writePos : 0; +} + +static bool SbufRawImplGrow(struct HdfSBufRaw *sbuf, uint32_t growSize) +{ + if (sbuf->isBind) { + HDF_LOGE("%s: binded sbuf oom", __func__); + return false; + } + + uint32_t newSize = SbufRawImplGetAlignSize(sbuf->capacity + growSize); + if (newSize < sbuf->capacity) { + HDF_LOGE("%s: grow size overflow", __func__); + return false; + } + if (newSize > HDF_SBUF_MAX_SIZE) { + HDF_LOGE("%s: buf size over limit", __func__); + return false; + } + + uint8_t *newData = OsalMemCalloc(newSize); + if (newData == NULL) { + HDF_LOGE("%s: oom", __func__); + return false; + } + + if (sbuf->data != NULL) { + if (memcpy_s(newData, newSize, sbuf->data, sbuf->writePos) != EOK) { + OsalMemFree(newData); + return false; + } + OsalMemFree(sbuf->data); + } + + sbuf->data = newData; + sbuf->capacity = newSize; + + return true; +} + +static bool SbufRawImplWrite(struct HdfSbufImpl *impl, const uint8_t *data, uint32_t size) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf == NULL || sbuf->data == NULL || data == NULL) { + return false; + } + + if (size == 0) { + return true; + } + + size_t alignSize = SbufRawImplGetAlignSize(size); + // in case of desireCapacity overflow + if (alignSize < size) { + HDF_LOGE("desireCapacity overflow"); + return false; + } + size_t writeableSize = SbufRawImplGetLeftWriteSize(sbuf); + if (alignSize > writeableSize) { + size_t growSize = (alignSize > HDF_SBUF_GROW_SIZE_DEFAULT) ? (alignSize + HDF_SBUF_GROW_SIZE_DEFAULT) + : HDF_SBUF_GROW_SIZE_DEFAULT; + if (!SbufRawImplGrow(sbuf, growSize)) { + return false; + } + writeableSize = SbufRawImplGetLeftWriteSize(sbuf); + } + + uint8_t *dest = sbuf->data + sbuf->writePos; + if (memcpy_s(dest, writeableSize, data, size) != EOK) { + return false; /* never hits */ + } + + sbuf->writePos += alignSize; + return true; +} + +static bool SbufRawImplRead(struct HdfSbufImpl *impl, uint8_t *data, uint32_t readSize) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf == NULL || sbuf->data == NULL || data == NULL) { + return false; + } + + if (readSize == 0) { + return true; + } + + size_t alignSize = SbufRawImplGetAlignSize(readSize); + if (alignSize > SbufRawImplGetLeftReadSize(sbuf)) { + HDF_LOGE("Read out of buffer range"); + return false; + } + + if (memcpy_s(data, readSize, sbuf->data + sbuf->readPos, readSize) != EOK) { + return false; // never hit + } + sbuf->readPos += alignSize; + return true; +} + +static bool SbufRawImplWriteUint64(struct HdfSbufImpl *impl, uint64_t value) +{ + return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value)); +} + +static bool SbufRawImplWriteUint32(struct HdfSbufImpl *impl, uint32_t value) +{ + return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value)); +} + +static bool SbufRawImplWriteUint16(struct HdfSbufImpl *impl, uint16_t value) +{ + return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value)); +} + +static bool SbufRawImplWriteUint8(struct HdfSbufImpl *impl, uint8_t value) +{ + return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value)); +} + +static bool SbufRawImplWriteInt64(struct HdfSbufImpl *impl, int64_t value) +{ + return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value)); +} + +static bool SbufRawImplWriteInt32(struct HdfSbufImpl *impl, int32_t value) +{ + return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value)); +} + +static bool SbufRawImplWriteInt16(struct HdfSbufImpl *impl, int16_t value) +{ + return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value)); +} + +static bool SbufRawImplWriteInt8(struct HdfSbufImpl *impl, int8_t value) +{ + return SbufRawImplWrite(impl, (uint8_t *)(&value), sizeof(value)); +} + +static bool SbufRawImplWriteBuffer(struct HdfSbufImpl *impl, const uint8_t *data, uint32_t writeSize) +{ + if (impl == NULL) { + HDF_LOGE("Failed to write the Sbuf, invalid input params"); + return false; + } + if (data == NULL) { + return SbufRawImplWriteInt32(impl, 0); + } + + if (!SbufRawImplWriteInt32(impl, writeSize)) { + return false; + } + if (!SbufRawImplWrite(impl, data, writeSize)) { + (void)SbufRawImplWriteRollback(impl, sizeof(int32_t)); + return false; + } + + return true; +} + +static bool SbufRawImplWriteString(struct HdfSbufImpl *impl, const char *value) +{ + if (impl == NULL) { + HDF_LOGE("%s: input null", __func__); + return false; + } + + return SbufRawImplWriteBuffer(impl, (const uint8_t *)value, value ? (strlen(value) + 1) : 0); +} + +static bool SbufRawImplReadUint64(struct HdfSbufImpl *impl, uint64_t *value) +{ + return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value)); +} + +static bool SbufRawImplReadUint32(struct HdfSbufImpl *impl, uint32_t *value) +{ + return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value)); +} + +static bool SbufRawImplReadUint16(struct HdfSbufImpl *impl, uint16_t *value) +{ + return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value)); +} + +static bool SbufRawImplReadUint8(struct HdfSbufImpl *impl, uint8_t *value) +{ + return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value)); +} + +static bool SbufRawImplReadInt64(struct HdfSbufImpl *impl, int64_t *value) +{ + return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value)); +} + +static bool SbufRawImplReadInt32(struct HdfSbufImpl *impl, int32_t *value) +{ + return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value)); +} + +static bool SbufRawImplReadInt16(struct HdfSbufImpl *impl, int16_t *value) +{ + return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value)); +} + +static bool SbufRawImplReadInt8(struct HdfSbufImpl *impl, int8_t *value) +{ + return SbufRawImplRead(impl, (uint8_t *)(value), sizeof(*value)); +} + +static bool SbufRawImplReadBuffer(struct HdfSbufImpl *impl, const uint8_t **data, uint32_t *readSize) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf == NULL || sbuf->data == NULL || data == NULL || readSize == NULL) { + HDF_LOGE("%s: input invalid", __func__); + return false; + } + + int buffSize = 0; + if (!SbufRawImplReadInt32(impl, &buffSize)) { + return false; + } + + if (buffSize == 0) { + *data = NULL; + *readSize = 0; + return true; + } + size_t alignSize = SbufRawImplGetAlignSize(buffSize); + if (alignSize > SbufRawImplGetLeftReadSize(sbuf)) { + HDF_LOGE("%s:readBuff out of range", __func__); + (void)SbufRawImplReadRollback(impl, sizeof(int32_t)); + return false; + } + + *data = sbuf->data + sbuf->readPos; + *readSize = buffSize; + sbuf->readPos += alignSize; + return true; +} + +static const char *SbufRawImplReadString(struct HdfSbufImpl *impl) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf == NULL || sbuf->data == NULL) { + HDF_LOGE("%s: input null", __func__); + return NULL; + } + /* This length contains the '\0' at the end of the string. */ + int32_t strLen = 0; + if (!SbufRawImplReadInt32(impl, &strLen) || strLen <= 0) { + return NULL; + } + size_t alignSize = SbufRawImplGetAlignSize(strLen); + if (strLen > INT16_MAX || alignSize > SbufRawImplGetLeftReadSize(sbuf)) { + (void)SbufRawImplReadRollback(impl, sizeof(int32_t)); + return NULL; + } + + char *str = (char *)(sbuf->data + sbuf->readPos); + sbuf->readPos += alignSize; + /* Set '\0' at end of the string forcibly. */ + str[strLen - 1] = '\0'; + return str; +} + +static struct HdfSbufImpl *SbufRawImplCopy(const struct HdfSbufImpl *impl) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf == NULL || sbuf->data == NULL) { + return NULL; + } + + struct HdfSBufRaw *new = SbufRawImplNewInstance(sbuf->capacity); + if (new == NULL) { + return NULL; + } + new->capacity = sbuf->capacity; + new->readPos = 0; + new->writePos = sbuf->writePos; + if (memcpy_s(new->data, new->capacity, sbuf->data, sbuf->capacity) != EOK) { + SbufRawImplRecycle(&new->infImpl); + return NULL; + } + + return &new->infImpl; +} + +static struct HdfSbufImpl *SbufRawImplMove(struct HdfSbufImpl *impl) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf == NULL || sbuf->isBind) { + return NULL; + } + + struct HdfSBufRaw *new = OsalMemCalloc(sizeof(struct HdfSBufRaw)); + if (new == NULL) { + return NULL; + } + new->capacity = sbuf->capacity; + new->readPos = 0; + new->writePos = sbuf->writePos; + new->data = sbuf->data; + + sbuf->data = NULL; + sbuf->capacity = 0; + SbufRawImplFlush(&sbuf->infImpl); + SbufInterfaceAssign(&new->infImpl); + + return &new->infImpl; +} + +static void SbufRawImplTransDataOwnership(struct HdfSbufImpl *impl) +{ + struct HdfSBufRaw *sbuf = SBUF_RAW_CAST(impl); + if (sbuf == NULL) { + return; + } + + sbuf->isBind = false; +} + +static void SbufInterfaceAssign(struct HdfSbufImpl *inf) +{ + inf->writeBuffer = SbufRawImplWriteBuffer; + inf->writeUint64 = SbufRawImplWriteUint64; + inf->writeUint32 = SbufRawImplWriteUint32; + inf->writeUint16 = SbufRawImplWriteUint16; + inf->writeUint8 = SbufRawImplWriteUint8; + inf->writeInt64 = SbufRawImplWriteInt64; + inf->writeInt32 = SbufRawImplWriteInt32; + inf->writeInt16 = SbufRawImplWriteInt16; + inf->writeInt8 = SbufRawImplWriteInt8; + inf->writeString = SbufRawImplWriteString; + inf->readBuffer = SbufRawImplReadBuffer; + inf->readUint64 = SbufRawImplReadUint64; + inf->readUint32 = SbufRawImplReadUint32; + inf->readUint16 = SbufRawImplReadUint16; + inf->readUint8 = SbufRawImplReadUint8; + inf->readInt64 = SbufRawImplReadInt64; + inf->readInt32 = SbufRawImplReadInt32; + inf->readInt16 = SbufRawImplReadInt16; + inf->readInt8 = SbufRawImplReadInt8; + inf->readString = SbufRawImplReadString; + inf->getData = SbufRawImplGetData; + inf->flush = SbufRawImplFlush; + inf->getCapacity = SbufRawImplGetCapacity; + inf->getDataSize = SbufRawImplGetDataSize; + inf->setDataSize = SbufRawImplSetDataSize; + inf->recycle = SbufRawImplRecycle; + inf->move = SbufRawImplMove; + inf->copy = SbufRawImplCopy; + inf->transDataOwnership = SbufRawImplTransDataOwnership; +} + +static struct HdfSBufRaw *SbufRawImplNewInstance(size_t capacity) +{ + if (capacity > HDF_SBUF_MAX_SIZE) { + HDF_LOGE("%s: Sbuf size exceeding max limit", __func__); + return NULL; + } + struct HdfSBufRaw *sbuf = (struct HdfSBufRaw *)OsalMemCalloc(sizeof(struct HdfSBufRaw)); + if (sbuf == NULL) { + HDF_LOGE("Sbuf instance failure"); + return NULL; + } + + sbuf->data = (uint8_t *)OsalMemCalloc(capacity); + if (sbuf->data == NULL) { + OsalMemFree(sbuf); + HDF_LOGE("sbuf obtain memory oom, size=%u", (uint32_t)capacity); + return NULL; + } + sbuf->capacity = capacity; + sbuf->writePos = 0; + sbuf->readPos = 0; + sbuf->isBind = false; + SbufInterfaceAssign(&sbuf->infImpl); + return sbuf; +} + +struct HdfSbufImpl *SbufObtainRaw(size_t capacity) +{ + struct HdfSBufRaw *sbuf = SbufRawImplNewInstance(capacity); + if (sbuf == NULL) { + return NULL; + } + return &sbuf->infImpl; +} + +struct HdfSbufImpl *SbufBindRaw(uintptr_t base, size_t size) +{ + if (base == 0 || size == 0) { + return NULL; + } + /* 4-byte alignment is required for base. */ + if ((base & 0x3) != 0) { + HDF_LOGE("Base not in 4-byte alignment"); + return NULL; + } + struct HdfSBufRaw *sbuf = (struct HdfSBufRaw *)OsalMemAlloc(sizeof(struct HdfSBufRaw)); + if (sbuf == NULL) { + HDF_LOGE("%s: oom", __func__); + return NULL; + } + + sbuf->data = (uint8_t *)base; + sbuf->capacity = size; + sbuf->writePos = size; + sbuf->readPos = 0; + sbuf->isBind = true; + SbufInterfaceAssign(&sbuf->infImpl); + return &sbuf->infImpl; +} \ No newline at end of file From 81b9092b75dd8b2acb408cc8db1adc2e4cbd16c8 Mon Sep 17 00:00:00 2001 From: gonghui Date: Mon, 17 May 2021 20:03:06 +0800 Subject: [PATCH 06/21] sync l2 code to l1 --- .../syscall/include/hdf_syscall_adapter.h | 2 +- core/adapter/syscall/src/hdf_devmgr_adapter.c | 16 +- .../adapter/syscall/src/hdf_syscall_adapter.c | 124 +++++---- core/adapter/vnode/src/hdf_vnode_adapter.c | 29 +- .../include/manager/devmgr_service_start.h | 6 +- core/common/src/devmgr_service_start.c | 17 +- core/common/src/hdf_attribute.c | 47 ++-- core/common/src/hdf_device_node_ext.c | 12 +- core/common/src/load_driver_entry.c | 16 +- core/host/include/devhost_service.h | 7 +- core/host/include/hdf_device.h | 5 +- core/host/include/hdf_device_node.h | 5 +- core/host/include/hdf_driver_loader.h | 2 + core/host/include/power_state_token.h | 8 +- core/host/src/devhost_service.c | 90 ++++--- core/host/src/devmgr_service_clnt.c | 8 +- core/host/src/devsvc_manager_clnt.c | 34 ++- core/host/src/hdf_device.c | 2 +- core/host/src/hdf_device_node.c | 35 ++- core/host/src/hdf_device_object.c | 47 +++- core/host/src/hdf_driver_loader.c | 33 ++- core/host/src/hdf_observer_record.c | 4 +- core/host/src/hdf_service_observer.c | 11 +- core/host/src/hdf_service_subscriber.c | 2 +- core/host/src/power_state_token.c | 189 ++++++++----- core/manager/include/devhost_service_clnt.h | 4 +- core/manager/include/devsvc_manager.h | 3 + core/manager/include/power_state_token_clnt.h | 2 +- core/manager/src/devhost_service_clnt.c | 11 +- core/manager/src/device_token_clnt.c | 2 +- core/manager/src/devmgr_service.c | 64 +++-- core/manager/src/devsvc_manager.c | 12 +- core/manager/src/hdf_driver_installer.c | 2 +- core/manager/src/power_state_manager.c | 1 - .../unittest/common/hdf_ioservice_test.cpp | 24 +- .../unittest/common/hdf_lite_manager_test.cpp | 10 +- .../test/unittest/common/hdf_sbuf_test.cpp | 67 +++-- core/sec/include/hdf_sec.h | 56 ++++ core/shared/include/hdf_device_info.h | 84 ++++++ core/shared/include/hdf_io_service.h | 4 +- core/shared/src/hdf_device_info.c | 3 + core/shared/src/hdf_service_record.c | 1 - include/config/device_resource_if.h | 10 +- include/core/hdf_device_desc.h | 17 +- include/core/hdf_object.h | 2 +- include/core/hdf_pm.h | 47 ++++ include/osal/osal_firmware.h | 28 +- include/osal/osal_sem.h | 2 + include/utils/hdf_dlist.h | 6 + utils/include/hdf_map.h | 40 +++ utils/include/hdf_message_looper.h | 32 +++ utils/include/hdf_message_task.h | 41 +++ utils/include/hdf_slist.h | 42 ++- utils/include/hdf_sref.h | 2 + utils/include/hdf_thread_ex.h | 38 +++ utils/include/osal_cdev.h | 50 ++++ utils/include/osal_message.h | 34 +++ utils/include/osal_msg_queue.h | 38 +++ utils/include/osal_sysevent.h | 49 ++++ utils/src/hdf_map.c | 254 ++++++++++++++++++ utils/src/hdf_message_looper.c | 53 ++++ utils/src/hdf_message_task.c | 59 ++++ utils/src/hdf_slist.c | 28 +- utils/src/hdf_sref.c | 11 + utils/src/hdf_thread_ex.c | 99 +++++++ utils/src/osal_message.c | 30 +++ utils/src/osal_msg_queue.c | 91 +++++++ 67 files changed, 1737 insertions(+), 467 deletions(-) mode change 100644 => 100755 core/host/src/hdf_driver_loader.c create mode 100644 core/sec/include/hdf_sec.h mode change 100644 => 100755 core/shared/include/hdf_device_info.h mode change 100644 => 100755 core/shared/src/hdf_device_info.c create mode 100644 include/core/hdf_pm.h create mode 100644 utils/include/hdf_map.h create mode 100644 utils/include/hdf_message_looper.h create mode 100644 utils/include/hdf_message_task.h create mode 100644 utils/include/hdf_thread_ex.h create mode 100644 utils/include/osal_cdev.h create mode 100644 utils/include/osal_message.h create mode 100644 utils/include/osal_msg_queue.h create mode 100644 utils/include/osal_sysevent.h create mode 100644 utils/src/hdf_map.c create mode 100644 utils/src/hdf_message_looper.c create mode 100644 utils/src/hdf_message_task.c create mode 100644 utils/src/hdf_thread_ex.c create mode 100644 utils/src/osal_message.c create mode 100644 utils/src/osal_msg_queue.c diff --git a/core/adapter/syscall/include/hdf_syscall_adapter.h b/core/adapter/syscall/include/hdf_syscall_adapter.h index 60de08bd..cb83b3f9 100644 --- a/core/adapter/syscall/include/hdf_syscall_adapter.h +++ b/core/adapter/syscall/include/hdf_syscall_adapter.h @@ -34,8 +34,8 @@ struct HdfDevListenerThread { struct pollfd *pfds; uint16_t pfdSize; bool pollChanged; - struct DListHead *listenerListPtr; bool shouldStop; + struct DListHead *listenerListPtr; uint8_t status; }; diff --git a/core/adapter/syscall/src/hdf_devmgr_adapter.c b/core/adapter/syscall/src/hdf_devmgr_adapter.c index 1d9b37cf..5a4e63e3 100644 --- a/core/adapter/syscall/src/hdf_devmgr_adapter.c +++ b/core/adapter/syscall/src/hdf_devmgr_adapter.c @@ -20,23 +20,23 @@ int32_t HdfLoadDriverByServiceName(const char *serviceName) } struct HdfIoService *ioService = HdfIoServiceBind(DEV_MGR_NODE); if (ioService == NULL) { - HDF_LOGE("Fail to get %s service", DEV_MGR_NODE); + HDF_LOGE("failed to get %s service", DEV_MGR_NODE); return ret; } data = HdfSBufObtainDefaultSize(); if (data == NULL) { - HDF_LOGE("fail to obtain sbuf data"); + HDF_LOGE("failed to obtain sbuf data"); ret = HDF_DEV_ERR_NO_MEMORY; goto out; } if (!HdfSbufWriteString(data, serviceName)) { - HDF_LOGE("fail to write sbuf"); + HDF_LOGE("failed to write sbuf"); ret = HDF_FAILURE; goto out; } ret = ioService->dispatcher->Dispatch(&ioService->object, DEVMGR_LOAD_SERVICE, data, NULL); if (ret != HDF_SUCCESS) { - HDF_LOGE("fail to send service call"); + HDF_LOGE("failed to load khdf driver %s", serviceName); } out: HdfIoServiceRecycle(ioService); @@ -54,23 +54,23 @@ int32_t HdfGetServiceNameByDeviceClass(DeviceClass deviceClass, struct HdfSBuf * } struct HdfIoService *ioService = HdfIoServiceBind(DEV_MGR_NODE); if (ioService == NULL) { - HDF_LOGE("Fail to get %s service", DEV_MGR_NODE); + HDF_LOGE("failed to get %s service", DEV_MGR_NODE); return ret; } data = HdfSBufObtainDefaultSize(); if (data == NULL) { - HDF_LOGE("fail to obtain sbuf data"); + HDF_LOGE("failed to obtain sbuf data"); ret = HDF_DEV_ERR_NO_MEMORY; goto out; } if (!HdfSbufWriteInt32(data, deviceClass)) { - HDF_LOGE("fail to write sbuf"); + HDF_LOGE("failed to write sbuf"); ret = HDF_FAILURE; goto out; } ret = ioService->dispatcher->Dispatch(&ioService->object, DEVMGR_GET_SERVICE, data, reply); if (ret != HDF_SUCCESS) { - HDF_LOGE("fail to send service call"); + HDF_LOGE("failed to query service by class"); } out: HdfIoServiceRecycle(ioService); diff --git a/core/adapter/syscall/src/hdf_syscall_adapter.c b/core/adapter/syscall/src/hdf_syscall_adapter.c index 2848d39c..c0d7bb60 100644 --- a/core/adapter/syscall/src/hdf_syscall_adapter.c +++ b/core/adapter/syscall/src/hdf_syscall_adapter.c @@ -95,7 +95,7 @@ static int32_t HdfDevEventDispatchLocked(const struct HdfDevListenerThread *thre return HDF_DEV_ERR_NO_MEMORY; } - /* dispatch event to SERVICE GROUP listener */ + /* Dispatch events to the service group listener */ if (thread->listenerListPtr != NULL) { DLIST_FOR_EACH_ENTRY(listener, thread->listenerListPtr, struct HdfDevEventlistener, listNode) { if (listener->onReceive != NULL) { @@ -103,21 +103,19 @@ static int32_t HdfDevEventDispatchLocked(const struct HdfDevListenerThread *thre } else if (listener->callBack != NULL) { (void)listener->callBack(listener->priv, bwr->cmdCode, sbuf); } - HdfSbufFlush(sbuf); - sbuf->writePos = bwr->readConsumed; + HdfSbufSetDataSize(sbuf, bwr->readConsumed); } } OsalMutexLock(&adapter->mutex); - /* dispatch event to SERVICE(SyscallAdapter) listener */ + /* Dispatch events to the service (SyscallAdapter) listener */ DLIST_FOR_EACH_ENTRY(listener, &adapter->listenerList, struct HdfDevEventlistener, listNode) { if (listener->onReceive != NULL) { (void)listener->onReceive(listener, &adapter->super, bwr->cmdCode, sbuf); } else if (listener->callBack != NULL) { (void)listener->callBack(listener->priv, bwr->cmdCode, sbuf); } - HdfSbufFlush(sbuf); - sbuf->writePos = bwr->readConsumed; + HdfSbufSetDataSize(sbuf, bwr->readConsumed); } OsalMutexUnlock(&adapter->mutex); @@ -131,20 +129,20 @@ static int32_t HdfDevEventReadAndDispatch(struct HdfDevListenerThread *thread, i int32_t ret = HDF_SUCCESS; bwr.readBuffer = (uintptr_t)OsalMemAlloc(HDF_DEFAULT_BWR_READ_SIZE); - bwr.cmdCode = -1; - bwr.readConsumed = 0; - bwr.readSize = HDF_DEFAULT_BWR_READ_SIZE; if (bwr.readBuffer == (uintptr_t)NULL) { HDF_LOGE("%s: oom", __func__); return HDF_DEV_ERR_NO_MEMORY; } + bwr.cmdCode = -1; + bwr.readConsumed = 0; + bwr.readSize = HDF_DEFAULT_BWR_READ_SIZE; OsalMutexLock(&thread->mutex); struct HdfSyscallAdapter *adapter = HdfFdToAdapterLocked(thread, fd); if (adapter == NULL) { - HDF_LOGI("%s:adapter invalid\n", __func__); - OsalMSleep(1); + HDF_LOGI("%s: invalid adapter", __func__); + OsalMSleep(1); // yield to sync adapter list goto finish; } @@ -156,7 +154,9 @@ static int32_t HdfDevEventReadAndDispatch(struct HdfDevListenerThread *thread, i ret = errno; if (ret == -HDF_DEV_ERR_NORANGE) { if (HdfDevEventGrowReadBuffer(&bwr) == HDF_SUCCESS) { - continue; /* read buffer may not enough, grow read buffer and try again */ + /* read buffer may not enough, grow read buffer and try again--The read buffere is insufficient. + Expand the buffer and try again. */ + continue; } } if (ret == -HDF_DEV_ERR_NODATA) { @@ -209,14 +209,6 @@ static int32_t AssignPfds(struct HdfDevListenerThread *thread, struct pollfd **p return pfdCount; } -static void HdfDevListenerThreadFree(struct HdfDevListenerThread *thread) -{ - OsalMutexDestroy(&thread->mutex); - OsalMemFree(thread->pfds); - OsalThreadDestroy(&thread->thread); - OsalMemFree(thread); -} - #define POLL_WAIT_TIME_MS 100 static int32_t HdfDevEventListenTask(void *para) { @@ -262,8 +254,11 @@ exit: OsalMemFree(pfds); if (thread->shouldStop) { - /* exit due to async exit call, should free thread struct */ - HdfDevListenerThreadFree(thread); + /* Exit due to async call and free the thread struct. */ + OsalMutexDestroy(&thread->mutex); + OsalThreadDestroy(&thread->thread); + OsalMemFree(thread->pfds); + OsalMemFree(thread); } return HDF_SUCCESS; @@ -273,7 +268,7 @@ static int32_t HdfAdapterStartListenIoctl(int fd) { int32_t ret = ioctl(fd, HDF_LISTEN_EVENT_START, 0); if (ret) { - HDF_LOGE("%s: fail to tell drv(%d) start %d %s", __func__, fd, errno, strerror(errno)); + HDF_LOGE("%s: failed to notify drv(%d) of start %d %s", __func__, fd, errno, strerror(errno)); return HDF_ERR_IO; } @@ -284,7 +279,7 @@ static int32_t HdfAdapterStopListenIoctl(int fd) { int32_t ret = ioctl(fd, HDF_LISTEN_EVENT_STOP, 0); if (ret) { - HDF_LOGE("%s: fail to tell drv stop %d %s", __func__, errno, strerror(errno)); + HDF_LOGE("%s: failed to notify drv(%d) of stop %d %s", __func__, fd, errno, strerror(errno)); return HDF_ERR_IO; } @@ -295,7 +290,7 @@ static int32_t HdfAdapterExitListenIoctl(int fd) { int32_t ret = ioctl(fd, HDF_LISTEN_EVENT_EXIT, 0); if (ret) { - HDF_LOGE("%s: fail to tell drv report exit %d %s", __func__, errno, strerror(errno)); + HDF_LOGE("%s: failed to notify drv(%d) of exit %d %s", __func__, fd, errno, strerror(errno)); return HDF_ERR_IO; } @@ -305,13 +300,13 @@ static int32_t HdfAdapterExitListenIoctl(int fd) static int32_t HdfDevListenerThreadDoInit(struct HdfDevListenerThread *thread) { if (OsalMutexInit(&thread->mutex) != HDF_SUCCESS) { - HDF_LOGE("%s: fail to create thread lock", __func__); + HDF_LOGE("%s: failed to create thread lock", __func__); return HDF_FAILURE; } int32_t ret = OsalThreadCreate(&thread->thread, HdfDevEventListenTask, thread); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: fail to create thread", __func__); + HDF_LOGE("%s: failed to create thread", __func__); thread->status = LISTENER_UNINITED; OsalMutexDestroy(&thread->mutex); return HDF_ERR_THREAD_CREATE_FAIL; @@ -499,7 +494,7 @@ static int32_t HdfIoServiceGroupThreadStart(struct HdfSyscallAdapterGroup *group static int32_t HdfListenThreadPollAdd(struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter) { - /* if thread is not bind to service group, not need to do poll add */ + /* If thread is not bound to a service group, you do not need to add a poll. */ if (thread->adapterListPtr == NULL) { return HDF_SUCCESS; } @@ -529,7 +524,7 @@ static int32_t HdfListenThreadPollAdd(struct HdfDevListenerThread *thread, struc if (headAdapter != NULL) { if (ioctl(headAdapter->fd, HDF_LISTEN_EVENT_WAKEUP, 0) != 0) { - HDF_LOGE("%s: fail to wakeup drv to add poll %d %s", __func__, errno, strerror(errno)); + HDF_LOGE("%s: failed to wakeup drv to add poll %d %s", __func__, errno, strerror(errno)); thread->pfds[index].fd = SYSCALL_INVALID_FD; ret = HDF_ERR_IO; break; @@ -568,11 +563,11 @@ static void HdfListenThreadPollDel(struct HdfDevListenerThread *thread, struct } if (HdfAdapterStopListenIoctl(adapter->fd)) { - HDF_LOGE("%s: fail to stop device report %d %s", __func__, errno, strerror(errno)); + HDF_LOGE("%s: failed to stop device report %d %s", __func__, errno, strerror(errno)); } if (ioctl(adapter->fd, HDF_LISTEN_EVENT_WAKEUP, 0) != 0) { - HDF_LOGE("%s: fail to wakeup drv to del poll %d %s", __func__, errno, strerror(errno)); + HDF_LOGE("%s: failed to wakeup drv to del poll %d %s", __func__, errno, strerror(errno)); } DListRemove(&adapter->listNode); adapter->group = NULL; @@ -580,6 +575,14 @@ static void HdfListenThreadPollDel(struct HdfDevListenerThread *thread, struct OsalMutexUnlock(&thread->mutex); } +static void HdfDevListenerThreadFree(struct HdfDevListenerThread *thread) +{ + OsalMutexDestroy(&thread->mutex); + OsalMemFree(thread->pfds); + OsalThreadDestroy(&thread->thread); + OsalMemFree(thread); +} + static void HdfDevListenerThreadDestroy(struct HdfDevListenerThread *thread) { if (thread == NULL) { @@ -648,10 +651,10 @@ static int32_t HdfSyscallAdapterDispatch(struct HdfObject *object, int32_t code, wrBuf.cmdCode = code; int32_t ret = ioctl(ioService->fd, HDF_WRITE_READ, &wrBuf); if (ret < 0) { - HDF_LOGE("dispatch serv call ioctl fail %d", errno); + HDF_LOGE("Failed to dispatch serv call ioctl %d", errno); } if (reply != NULL) { - reply->writePos = wrBuf.readConsumed; + HdfSbufSetDataSize(reply, wrBuf.readConsumed); } return ret; } @@ -660,41 +663,48 @@ struct HdfIoService *HdfIoServiceAdapterObtain(const char *serviceName) { struct HdfSyscallAdapter *adapter = NULL; struct HdfIoService *ioService = NULL; - char devNodePath[PATH_MAX] = {0}; - char realPath[PATH_MAX] = {0}; + char *devNodePath = NULL; + char *realPath = NULL; const char *devPath = DEV_NODE_PATH; if (access(DEV_NODE_PATH, F_OK) != 0) { devPath = DEV_PATH; } + devNodePath = OsalMemCalloc(PATH_MAX); + realPath = OsalMemCalloc(PATH_MAX); + if (devNodePath == NULL || realPath == NULL) { + HDF_LOGE("%s: out of memory", __func__); + goto out; + } + if (sprintf_s(devNodePath, PATH_MAX - 1, "%s%s", devPath, serviceName) < 0) { - HDF_LOGE("Get node path failed"); - return NULL; + HDF_LOGE("Failed to get the node path"); + goto out; } if (realpath(devNodePath, realPath) == NULL) { if (HdfLoadDriverByServiceName(serviceName) != HDF_SUCCESS) { - HDF_LOGE("%s load %s driver failed", __func__, serviceName); - return NULL; + HDF_LOGE("%s: load %s driver failed", __func__, serviceName); + goto out; } if (realpath(devNodePath, realPath) == NULL) { - HDF_LOGE("%s file name %s is invalid", __func__, devNodePath); - return NULL; + HDF_LOGE("%s: file name %s is invalid", __func__, devNodePath); + goto out; } } adapter = (struct HdfSyscallAdapter *)OsalMemCalloc(sizeof(struct HdfSyscallAdapter)); if (adapter == NULL) { - HDF_LOGE("Alloc syscall adapter failed"); - return NULL; + HDF_LOGE("Failed to allocate SyscallAdapter"); + goto out; } DListHeadInit(&adapter->listenerList); if (OsalMutexInit(&adapter->mutex)) { - HDF_LOGE("%s: create mutex fail", __func__); + HDF_LOGE("%s: Failed to create mutex", __func__); OsalMemFree(adapter); - return NULL; + goto out; } adapter->fd = open(realPath, O_RDWR); @@ -702,13 +712,16 @@ struct HdfIoService *HdfIoServiceAdapterObtain(const char *serviceName) HDF_LOGE("Open file node %s failed, (%d)%s", realPath, errno, strerror(errno)); OsalMutexDestroy(&adapter->mutex); OsalMemFree(adapter); - return NULL; + goto out; } ioService = &adapter->super; static struct HdfIoDispatcher dispatch = { .Dispatch = HdfSyscallAdapterDispatch, }; ioService->dispatcher = &dispatch; +out: + OsalMemFree(devNodePath); + OsalMemFree(realPath); return ioService; } @@ -743,7 +756,7 @@ static int32_t HdfIoServiceThreadBindLocked(struct HdfSyscallAdapter *adapter) static int32_t HdfIoServiceStartListen(struct HdfSyscallAdapter *adapter) { if (HdfIoServiceThreadBindLocked(adapter) != HDF_SUCCESS) { - HDF_LOGE("%s:adapter bind thread fail", __func__); + HDF_LOGE("%s: Failed to bind a thread to SyscallAdapter", __func__); return HDF_FAILURE; } @@ -755,7 +768,7 @@ static bool AddListenerToAdapterLocked(struct HdfSyscallAdapter *adapter, struct struct HdfDevEventlistener *it = NULL; DLIST_FOR_EACH_ENTRY(it, &adapter->listenerList, struct HdfDevEventlistener, listNode) { if (it == listener) { - HDF_LOGE("add duplicate dev-event listener"); + HDF_LOGE("Add a listener for duplicate dev-event"); return false; } } @@ -770,7 +783,7 @@ int32_t HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDe } if (listener->callBack == NULL && listener->onReceive == NULL) { - HDF_LOGE("listenr onReceive func not implement"); + HDF_LOGE("Listenr onReceive func not implemented"); return HDF_ERR_INVALID_OBJECT; } @@ -784,8 +797,9 @@ int32_t HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDe } if (adapter->group != NULL) { - /* service in group, should not bind to self hold thread and try to start group thread */ + /* Do not bind any service in a service goup to its own thread or start the group thread. */ ret = HdfIoServiceGroupThreadStart(adapter->group); + DListRemove(&listener->listNode); OsalMutexUnlock(&adapter->mutex); return ret; } @@ -806,7 +820,7 @@ int32_t HdfDeviceUnregisterEventListener(struct HdfIoService *target, struct Hdf } if (listener->listNode.next == NULL || listener->listNode.prev == NULL) { - HDF_LOGE("%s:broken listener, may double unregister", __func__); + HDF_LOGE("%s: broken listener, may double unregister", __func__); return HDF_ERR_INVALID_OBJECT; } @@ -872,7 +886,7 @@ int32_t HdfIoServiceGroupRegisterListener(struct HdfIoServiceGroup *group, struc } if (listener->callBack == NULL && listener->onReceive == NULL) { - HDF_LOGE("listenr onReceive func not implement"); + HDF_LOGE("listenr onReceive func not implemented"); return HDF_ERR_INVALID_OBJECT; } struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup); @@ -891,8 +905,8 @@ int32_t HdfIoServiceGroupRegisterListener(struct HdfIoServiceGroup *group, struc struct HdfDevEventlistener *it = NULL; DLIST_FOR_EACH_ENTRY(it, &adapterGroup->listenerList, struct HdfDevEventlistener, listNode) { if (it == listener) { - HDF_LOGE("add group listener failed, repeated registration"); - ret = HDF_ERR_INVALID_OBJECT; + HDF_LOGE("Failed to add group listener, repeated registration"); + ret = HDF_ERR_INVALID_PARAM; goto finish; } } @@ -917,7 +931,7 @@ static int32_t GetListenerCount(struct HdfDevListenerThread *thread) OsalMutexLock(&thread->mutex); if (thread->listenerListPtr != NULL) { - DLIST_FOR_EACH_ENTRY (listener, thread->listenerListPtr, struct HdfDevEventlistener, listNode) { + DLIST_FOR_EACH_ENTRY(listener, thread->listenerListPtr, struct HdfDevEventlistener, listNode) { count++; } } diff --git a/core/adapter/vnode/src/hdf_vnode_adapter.c b/core/adapter/vnode/src/hdf_vnode_adapter.c index 0d39bd60..f1ddc1ba 100644 --- a/core/adapter/vnode/src/hdf_vnode_adapter.c +++ b/core/adapter/vnode/src/hdf_vnode_adapter.c @@ -20,7 +20,7 @@ #define HDF_LOG_TAG hdf_vnode #define VOID_DATA_SIZE 4 #define EVENT_QUEUE_MAX 100 -#define MAX_RW_SIZE (1024*1204) // 1M +#define MAX_RW_SIZE (1024 * 1204) // 1M enum HdfVNodeClientStatus { VNODE_CLIENT_RUNNING, @@ -99,7 +99,7 @@ struct HdfIoService *HdfIoServiceAdapterObtain(const char *serviceName) } svcMgr = DevSvcManagerClntGetInstance(); - if (svcMgr == NULL) { + if (svcMgr == NULL || svcMgr->devSvcMgrIf == NULL) { return NULL; } deviceObject = svcMgr->devSvcMgrIf->GetObject(svcMgr->devSvcMgrIf, serviceName); @@ -146,7 +146,7 @@ static struct HdfSBuf *HdfSbufCopyFromUser(uintptr_t data, size_t size) return NULL; } if (CopyFromUser((void*)kData, (void*)data, size) != 0) { - HDF_LOGE("%s:copy from user fail", __func__); + HDF_LOGE("%s:failed to copy from user", __func__); OsalMemFree(kData); return NULL; } @@ -172,7 +172,7 @@ static int HdfSbufCopyToUser(const struct HdfSBuf *sbuf, void *dstUser, size_t d } if (CopyToUser(dstUser, HdfSbufGetData(sbuf), sbufSize) != 0) { - HDF_LOGE("%s: copy buff data fail", __func__); + HDF_LOGE("%s: failed to copy buff data", __func__); return HDF_ERR_IO; } @@ -207,7 +207,7 @@ static int HdfVNodeAdapterServCall(const struct HdfVNodeAdapterClient *client, u return HDF_ERR_INVALID_PARAM; } if (CopyFromUser(&bwr, (void*)bwrUser, sizeof(bwr)) != 0) { - HDF_LOGE("Copy from user failed"); + HDF_LOGE("copy from user failed"); return HDF_FAILURE; } if (bwr.writeSize > MAX_RW_SIZE || bwr.readSize > MAX_RW_SIZE) { @@ -216,12 +216,12 @@ static int HdfVNodeAdapterServCall(const struct HdfVNodeAdapterClient *client, u data = HdfSbufCopyFromUser(bwr.writeBuffer, bwr.writeSize); if (data == NULL) { - HDF_LOGE("Vnode adapter bind data is null"); + HDF_LOGE("vnode adapter bind data is null"); return HDF_FAILURE; } reply = HdfSBufObtainDefaultSize(); if (reply == NULL) { - HDF_LOGE("%s:oom", __func__); + HDF_LOGE("%s: oom", __func__); HdfSBufRecycle(data); return HDF_FAILURE; } @@ -235,7 +235,7 @@ static int HdfVNodeAdapterServCall(const struct HdfVNodeAdapterClient *client, u } bwr.readConsumed = HdfSbufGetDataSize(reply); if (CopyToUser(bwrUser, &bwr, sizeof(struct HdfWriteReadBuf)) != 0) { - HDF_LOGE("%s: copy bwr fail", __func__); + HDF_LOGE("%s: fail to copy bwr", __func__); ret = HDF_FAILURE; } @@ -286,7 +286,7 @@ static int HdfVNodeAdapterReadDevEvent(struct HdfVNodeAdapterClient *client, uns } if (CopyToUser(bwrUser, &bwr, sizeof(struct HdfWriteReadBuf)) != 0) { - HDF_LOGE("%s: copy bwr fail", __func__); + HDF_LOGE("%s: failed to copy bwr", __func__); ret = HDF_ERR_IO; } if (ret == HDF_SUCCESS) { @@ -461,7 +461,6 @@ static struct HdfVNodeAdapterClient *HdfNewVNodeAdapterClient(struct HdfVNodeAda client->serv = &adapter->ioService; client->status = VNODE_CLIENT_RUNNING; client->adapter = adapter; - client->eventQueueSize = 0; client->ioServiceClient.device = (struct HdfDeviceObject *)adapter->ioService.target; client->ioServiceClient.priv = NULL; client->wakeup = 0; @@ -565,26 +564,26 @@ struct HdfIoService *HdfIoServiceAdapterPublish(const char *serviceName, uint32_ }; if ((serviceName == NULL) || (mode > MAX_MODE_SIZE)) { - HDF_LOGE("Input param is invalid, mode is %x", mode); + HDF_LOGE("input param is invalid, mode is %x", mode); return NULL; } vnodeAdapter = (struct HdfVNodeAdapter *)OsalMemCalloc(sizeof(struct HdfVNodeAdapter)); if (vnodeAdapter == NULL) { - HDF_LOGE("Alloc remote service is null"); + HDF_LOGE("alloc remote service is null"); return NULL; } nodePathLength = strlen(serviceName) + strlen(DEV_NODE_PATH) + 1; vnodeAdapter->vNodePath = (char *)OsalMemCalloc(nodePathLength); if (vnodeAdapter->vNodePath == NULL) { - HDF_LOGE("Alloc vnode path is null"); + HDF_LOGE("alloc vnode path is null"); OsalMemFree(vnodeAdapter); return NULL; } if (sprintf_s(vnodeAdapter->vNodePath, nodePathLength, "%s%s", DEV_NODE_PATH, serviceName) < 0) { - HDF_LOGE("Get node path failed"); + HDF_LOGE("failed to get node path"); OsalMemFree(vnodeAdapter->vNodePath); OsalMemFree(vnodeAdapter); return NULL; @@ -602,7 +601,7 @@ struct HdfIoService *HdfIoServiceAdapterPublish(const char *serviceName, uint32_ } ret = OsalRegisterCdev(vnodeAdapter->cdev, vnodeAdapter->vNodePath, mode, vnodeAdapter); if (ret != 0) { - HDF_LOGE("register dev node %s failed, ret is: %d", vnodeAdapter->vNodePath, ret); + HDF_LOGE("failed to register dev node %s, ret is: %d", vnodeAdapter->vNodePath, ret); OsalMutexDestroy(&vnodeAdapter->mutex); goto error; } diff --git a/core/common/include/manager/devmgr_service_start.h b/core/common/include/manager/devmgr_service_start.h index 6a2d571e..8f6f675b 100644 --- a/core/common/include/manager/devmgr_service_start.h +++ b/core/common/include/manager/devmgr_service_start.h @@ -6,8 +6,8 @@ * See the LICENSE file in the root of this repository for complete details. */ -#ifndef DEVICE_SERVICE_START_H -#define DEVICE_SERVICE_START_H +#ifndef DEVMGR_SERVICE_START_H +#define DEVMGR_SERVICE_START_H enum { DEV_MGR_SLOW_LOAD = 0, @@ -19,4 +19,4 @@ int DeviceManagerStartStep2(void); void DeviceManagerSetQuickLoad(int isQuickLoad); int DeviceManagerIsQuickLoad(void); -#endif /* DEVICE_SERVICE_START_H */ +#endif /* DEVMGR_SERVICE_START_H */ diff --git a/core/common/src/devmgr_service_start.c b/core/common/src/devmgr_service_start.c index 143e05cc..6dbaa074 100644 --- a/core/common/src/devmgr_service_start.c +++ b/core/common/src/devmgr_service_start.c @@ -31,8 +31,7 @@ static void GetDeviceServiceNameByClass(DeviceClass deviceClass, struct HdfSBuf return; } - reply->readPos = 0; - reply->writePos = 0; + HdfSbufFlush(reply); HdfSListIteratorInit(&itHost, &devMgrSvc->hosts); while (HdfSListIteratorHasNext(&itHost)) { hostClnt = (struct DevHostServiceClnt *)HdfSListIteratorNext(&itHost); @@ -78,21 +77,21 @@ int DeviceManagerDispatch(struct HdfObject *stub, int code, struct HdfSBuf *data case DEVMGR_UNLOAD_SERVICE: svcName = HdfSbufReadString(data); if (svcName == NULL) { - HDF_LOGE("%s: get svc name is null", __func__); + HDF_LOGE("%s: svc name is null", __func__); break; } ret = DevSvcManagerClntUnsubscribeService(svcName); break; case DEVMGR_GET_SERVICE: if (!HdfSbufReadInt32(data, &deviceClass)) { - HDF_LOGE("%s: get deviceClass failed", __func__); + HDF_LOGE("%s: failed to get deviceClass", __func__); break; } GetDeviceServiceNameByClass(deviceClass, reply); ret = HDF_SUCCESS; break; default: - HDF_LOGE("%s: Currently, this configuration type is not supported. the type is %d", __func__, code); + HDF_LOGE("%s: unsupported configuration type: %d", __func__, code); break; } OsalMutexUnlock(&devMgrSvc->devMgrMutex); @@ -104,17 +103,17 @@ void DeviceManagerSetQuickLoad(int loadFlag) g_isQuickLoad = loadFlag; } -int DeviceManagerIsQuickLoad() +int DeviceManagerIsQuickLoad(void) { return g_isQuickLoad; } -int DeviceManagerStart() +int DeviceManagerStart(void) { struct IDevmgrService *instance = DevmgrServiceGetInstance(); if (instance == NULL || instance->StartService == NULL) { - HDF_LOGE("Device manager start failed, service instance is null!"); + HDF_LOGE("device manager start failed, service instance is null"); return HDF_FAILURE; } struct HdfIoService *ioService = HdfIoServicePublish(DEV_MGR_NODE, DEV_MGR_NODE_PERM); @@ -131,7 +130,7 @@ int DeviceManagerStart() int DeviceManagerStartStep2() { if (DeviceManagerIsQuickLoad() == DEV_MGR_SLOW_LOAD) { - HDF_LOGW("%s device manager is not set quick load!", __func__); + HDF_LOGW("%s: device manager is not set to QuickLoad mode", __func__); return HDF_SUCCESS; } struct DevmgrService *devMgrSvc = (struct DevmgrService *)DevmgrServiceGetInstance(); diff --git a/core/common/src/hdf_attribute.c b/core/common/src/hdf_attribute.c index 1d696fab..83b609fd 100644 --- a/core/common/src/hdf_attribute.c +++ b/core/common/src/hdf_attribute.c @@ -32,6 +32,7 @@ static struct DeviceResourceNode *g_hcsTreeRoot = NULL; void HdfGetBuildInConfigData(const unsigned char **data, unsigned int *size); + static bool CreateHcsToTree(void) { uint32_t length; @@ -49,7 +50,7 @@ static bool CreateHcsToTree(void) const struct DeviceResourceNode *HcsGetRootNode(void) { if ((g_hcsTreeRoot == NULL) && !CreateHcsToTree()) { - HDF_LOGE("%s failed", __func__); + HDF_LOGE("%s: failed", __func__); return NULL; } return g_hcsTreeRoot; @@ -80,12 +81,12 @@ static bool GetHostInfo(const struct DeviceResourceNode *hostNode, struct HdfHos uint16_t readNum = 0; if ((HcsGetString(hostNode, ATTR_HOST_NAME, &hostInfo->hostName, NULL) != HDF_SUCCESS) || (strcmp(hostInfo->hostName, "") == 0)) { - HDF_LOGW("%s get host name failed", __func__); + HDF_LOGW("%s: get host name failed", __func__); return false; } if ((HcsGetUint16(hostNode, ATTR_DEV_PRIORITY, &readNum, 0) != HDF_SUCCESS) || (readNum > MAX_PRIORITY_NUM)) { - HDF_LOGW("%s get host priority failed, priority is: %d", __func__, readNum); + HDF_LOGW("%s: get host priority failed, priority is: %u", __func__, readNum); return false; } hostInfo->priority = readNum; @@ -103,7 +104,7 @@ bool HdfAttributeManagerGetHostList(struct HdfSList *hostList) hdfManagerNode = GetHdfManagerNode(HcsGetRootNode()); if (hdfManagerNode == NULL) { - HDF_LOGE("%s get hdf manager node is null", __func__); + HDF_LOGE("%s: get hdf manager node is null", __func__); return false; } @@ -112,19 +113,17 @@ bool HdfAttributeManagerGetHostList(struct HdfSList *hostList) struct HdfHostInfo *hostInfo = HdfHostInfoNewInstance(); if (hostInfo == NULL) { HdfSListFlush(hostList, HdfHostInfoDelete); - HDF_LOGE("%s new hostInfo is null", __func__); + HDF_LOGE("%s: new hostInfo is null", __func__); return false; } if (!GetHostInfo(hostNode, hostInfo)) { HdfHostInfoFreeInstance(hostInfo); - hostInfo = NULL; hostNode = hostNode->sibling; continue; } hostInfo->hostId = hostId; if (!HdfSListAddOrder(hostList, &hostInfo->node, HdfHostListCompare)) { HdfHostInfoFreeInstance(hostInfo); - hostInfo = NULL; hostNode = hostNode->sibling; continue; } @@ -149,7 +148,9 @@ static const struct DeviceResourceNode *GetHostNode(const char *inHostName) const struct DeviceResourceNode *hdfManagerNode = NULL; const struct DeviceResourceNode *hostNode = NULL; const char *hostName = NULL; - + if (inHostName == NULL) { + return NULL; + } hdfManagerNode = GetHdfManagerNode(HcsGetRootNode()); if (hdfManagerNode == NULL) { return NULL; @@ -171,17 +172,17 @@ static const struct DeviceResourceNode *GetHostNode(const char *inHostName) static bool CheckDeviceInfo(const struct HdfDeviceInfo *deviceNodeInfo) { if (deviceNodeInfo->policy > SERVICE_POLICY_PRIVATE) { - HDF_LOGE("%s policy is invalid", __func__); + HDF_LOGE("%s: policy %u is invalid", __func__, deviceNodeInfo->policy); return false; } if (deviceNodeInfo->priority > MAX_PRIORITY_NUM) { - HDF_LOGE("%s priority is invalid", __func__); + HDF_LOGE("%s: priority %u is invalid", __func__, deviceNodeInfo->priority); return false; } if (deviceNodeInfo->preload > DEVICE_PRELOAD_DISABLE) { - HDF_LOGE("%s preload is invalid", __func__); + HDF_LOGE("%s: preload %u is invalid", __func__, deviceNodeInfo->preload); return false; } @@ -193,43 +194,43 @@ static bool GetDeviceNodeInfo(const struct DeviceResourceNode *deviceNode, struc uint16_t readNum = 0; const char *readString = NULL; if (HcsGetUint16(deviceNode, ATTR_DEV_POLICY, &readNum, 0) != HDF_SUCCESS) { - HDF_LOGE("%s get policy failed", __func__); + HDF_LOGE("%s: failed to get policy", __func__); return false; } deviceNodeInfo->policy = readNum; if (HcsGetUint16(deviceNode, ATTR_DEV_PRIORITY, &readNum, 0) != HDF_SUCCESS) { - HDF_LOGE("%s get priority failed", __func__); + HDF_LOGE("%s: failed to get priority", __func__); return false; } deviceNodeInfo->priority = readNum; if (HcsGetUint16(deviceNode, ATTR_DEV_PRELOAD, &readNum, 0) != HDF_SUCCESS) { - HDF_LOGE("%s get preload failed", __func__); + HDF_LOGE("%s: failed to get preload", __func__); return false; } deviceNodeInfo->preload = readNum; if (HcsGetUint16(deviceNode, ATTR_DEV_PERMISSION, &readNum, 0) != HDF_SUCCESS) { - HDF_LOGE("%s get permission failed", __func__); + HDF_LOGE("%s: failed to get permission", __func__); return false; } deviceNodeInfo->permission = readNum; if (HcsGetString(deviceNode, ATTR_DEV_MODULENAME, &readString, NULL) != HDF_SUCCESS) { - HDF_LOGE("%s get module name failed", __func__); + HDF_LOGE("%s: failed to get module name", __func__); return false; } deviceNodeInfo->moduleName = readString; if (HcsGetString(deviceNode, ATTR_DEV_SVCNAME, &readString, NULL) != HDF_SUCCESS) { - HDF_LOGE("%s get service name failed", __func__); + HDF_LOGE("%s: failed to get service name", __func__); return false; } deviceNodeInfo->svcName = readString; if (HcsGetString(deviceNode, ATTR_DEV_MATCHATTR, &readString, NULL) != HDF_SUCCESS) { - HDF_LOGE("%s get service name failed", __func__); + HDF_LOGE("%s: failed to get matchattr name", __func__); return false; } deviceNodeInfo->deviceMatchAttr = readString; @@ -260,13 +261,13 @@ struct HdfSList *HdfAttributeManagerGetDeviceList(uint16_t hostId, const char *h deviceNodeInfo->hostId = hostId; if (!GetDeviceNodeInfo(deviceNode, deviceNodeInfo)) { HdfDeviceInfoFreeInstance(deviceNodeInfo); - HDF_LOGE("%s get device failed", __func__); + HDF_LOGE("%s: failed to get device", __func__); deviceNodeInfo = NULL; deviceNode = deviceNode->sibling; continue; } if (!HdfSListAddOrder(deviceList, &deviceNodeInfo->node, HdfDeviceListCompare)) { - HDF_LOGE("%s add device %s failed", __func__, deviceNodeInfo->svcName); + HDF_LOGE("%s: failed to add device %s", __func__, deviceNodeInfo->svcName); HdfDeviceInfoFreeInstance(deviceNodeInfo); deviceNodeInfo = NULL; deviceNode = deviceNode->sibling; @@ -323,7 +324,11 @@ bool HdfDeviceListAdd(const char *moduleName, const char *serviceName) if (svcName == NULL) { break; } - strcpy(svcName, serviceName); + if (strcpy_s(svcName, strlen(serviceName) + 1, serviceName) != EOK) { + HDF_LOGE("%s: failed to copy string", __func__); + OsalMemFree(svcName); + break; + } deviceNodeInfo->svcName = svcName; HdfSListAdd(hostClnt->deviceInfos, &deviceNodeInfo->node); hostClnt->devCount++; diff --git a/core/common/src/hdf_device_node_ext.c b/core/common/src/hdf_device_node_ext.c index 493cd51e..a8143a44 100644 --- a/core/common/src/hdf_device_node_ext.c +++ b/core/common/src/hdf_device_node_ext.c @@ -24,29 +24,29 @@ static int DeviceNodeExtDispatch(struct HdfObject *stub, int code, struct HdfSBu struct HdfDeviceNode *devNode = NULL; if (stub == NULL) { - HDF_LOGE("input ioService null"); + HDF_LOGE("device ext dispatch: stub is null"); return HDF_FAILURE; } uint64_t ioClientPtr = 0; if (!HdfSbufReadUint64(reply, &ioClientPtr) || ioClientPtr == 0) { - HDF_LOGE("input ioClient null"); + HDF_LOGE("device ext dispatch: input ioClient is null"); return HDF_FAILURE; } HdfSbufFlush(reply); devNode = CONTAINER_OF(stub, struct HdfDeviceNode, deviceObject); deviceMethod = devNode->deviceObject.service; if (deviceMethod == NULL) { - HDF_LOGE("Device service interface is null"); + HDF_LOGE("device ext dispatch: device service interface is null"); return HDF_FAILURE; } deviceInfo = devNode->deviceInfo; if (deviceInfo == NULL) { - HDF_LOGE("Device deviceInfo is null"); + HDF_LOGE("device ext dispatch: device deviceInfo is null"); return HDF_FAILURE; } if (deviceInfo->policy == SERVICE_POLICY_CAPACITY) { if (deviceMethod->Dispatch == NULL) { - HDF_LOGE("Remote service dispatch is null"); + HDF_LOGE("device ext dispatch: remote service dispatch method is null"); return HDF_FAILURE; } return deviceMethod->Dispatch((struct HdfDeviceIoClient *)((uintptr_t)ioClientPtr), code, data, reply); @@ -64,7 +64,7 @@ static int DeviceNodeExtPublishService(struct HdfDeviceNode *inst, const char *s } int ret = HdfDeviceNodePublishPublicService(inst, serviceName); if (ret != HDF_SUCCESS) { - HDF_LOGE("Device publish service failed, ret is: %d", ret); + HDF_LOGE("failed to publish device service, ret is %d", ret); return HDF_FAILURE; } diff --git a/core/common/src/load_driver_entry.c b/core/common/src/load_driver_entry.c index 39e420a4..9a42ecbd 100644 --- a/core/common/src/load_driver_entry.c +++ b/core/common/src/load_driver_entry.c @@ -15,12 +15,12 @@ static struct HdfDriverEntry *HdfDriverEntryConstruct(int32_t *driverCount) int i; *driverCount = (int32_t)(((uint8_t *)(HDF_DRIVER_END()) - (uint8_t *)(HDF_DRIVER_BEGIN())) / sizeof(size_t)); if (*driverCount <= 0) { - HDF_LOGE("%s hdf get device counts failed!", __func__); + HDF_LOGE("%s: failed to hdf get device counts", __func__); return NULL; } struct HdfDriverEntry *driverEntry = OsalMemCalloc(*driverCount * sizeof(struct HdfDriverEntry)); if (driverEntry == NULL) { - HDF_LOGE("%s hdf alloc driver entry mem failed!", __func__); + HDF_LOGE("%s: failed to alloc driver entry mem", __func__); *driverCount = 0; return NULL; } @@ -36,7 +36,7 @@ struct HdfDriverEntry *HdfDriverLoaderGetDriverEntry(const struct HdfDeviceInfo { int i; if ((deviceInfo == NULL) || (deviceInfo->moduleName == NULL) || (deviceInfo->svcName == NULL)) { - HDF_LOGE("%s hdf get device entry failed, input deviceInfo is NULL!", __func__); + HDF_LOGE("%s: failed to get device entry, input deviceInfo is NULL", __func__); return NULL; } static struct HdfDriverEntry *driverEntry = NULL; @@ -44,24 +44,24 @@ struct HdfDriverEntry *HdfDriverLoaderGetDriverEntry(const struct HdfDeviceInfo if (driverEntry == NULL) { driverEntry = HdfDriverEntryConstruct(&driverCount); if (driverEntry == NULL) { - HDF_LOGE("%s driver entry construct failed!", __func__); + HDF_LOGE("%s: failed to construct driver entry", __func__); return NULL; } } for (i = 0; i < driverCount; i++) { if (driverEntry == NULL) { - HDF_LOGE("%s driver entry is null!", __func__); + HDF_LOGE("%s: driver entry is null", __func__); return NULL; } if (driverEntry[i].moduleName == NULL) { - HDF_LOGE("%s driver entry module name is null!", __func__); - return NULL; + HDF_LOGE("%s: driver entry module name is null", __func__); + continue; } if (strcmp(deviceInfo->moduleName, driverEntry[i].moduleName) == 0) { return &driverEntry[i]; } } - HDF_LOGE("Hdf get %s device entry failed!", deviceInfo->svcName); + HDF_LOGE("failed to get device entry %s", deviceInfo->svcName); return NULL; } diff --git a/core/host/include/devhost_service.h b/core/host/include/devhost_service.h index 26d8972c..eb7347ee 100644 --- a/core/host/include/devhost_service.h +++ b/core/host/include/devhost_service.h @@ -11,20 +11,23 @@ #include "devhost_service_if.h" #include "hdf_service_observer.h" -#include "hdf_slist.h" +#include "hdf_dlist.h" #include "osal_mutex.h" +#include "osal_sysevent.h" struct DevHostService { struct IDevHostService super; uint16_t hostId; const char *hostName; - struct HdfSList devices; + struct DListHead devices; struct HdfServiceObserver observer; + struct HdfSysEventNotifyNode sysEventNotifyNode; }; void DevHostServiceConstruct(struct DevHostService *service); void DevHostServiceDestruct(struct DevHostService *service); int DevHostServiceAddDevice(struct IDevHostService *inst, const struct HdfDeviceInfo *deviceInfo); +int DevHostServiceDelDevice(struct IDevHostService *inst, const struct HdfDeviceInfo *deviceInfo); struct IDevHostService *DevHostServiceNewInstance(uint16_t hostId, const char *hostName); void DevHostServiceFreeInstance(struct IDevHostService *service); struct HdfObject *DevHostServiceCreate(void); diff --git a/core/host/include/hdf_device.h b/core/host/include/hdf_device.h index c14e9901..e15132a1 100644 --- a/core/host/include/hdf_device.h +++ b/core/host/include/hdf_device.h @@ -14,7 +14,7 @@ #include "hdf_device_desc.h" #include "hdf_object.h" #include "hdf_service_observer.h" -#include "hdf_slist.h" +#include "hdf_dlist.h" #include "osal_mutex.h" struct HdfDeviceNode; @@ -22,11 +22,12 @@ struct HdfDeviceNode; struct IHdfDevice { struct HdfObject object; int (*Attach)(struct IHdfDevice *, struct HdfDeviceNode *); + void (*Detach)(struct IHdfDevice *, struct HdfDeviceNode *); }; struct HdfDevice { struct IHdfDevice super; - struct HdfSListNode node; + struct DListHead node; struct HdfSList services; uint16_t deviceId; uint16_t hostId; diff --git a/core/host/include/hdf_device_node.h b/core/host/include/hdf_device_node.h index aee06dd2..87b9da5f 100644 --- a/core/host/include/hdf_device_node.h +++ b/core/host/include/hdf_device_node.h @@ -12,6 +12,7 @@ #include "hdf_device.h" #include "hdf_device_info.h" #include "hdf_device_desc.h" +#include "hdf_pm.h" struct HdfDeviceNode; struct DevHostService; @@ -34,7 +35,9 @@ struct HdfDeviceNode { }; int HdfDeviceNodeAddPowerStateListener( - struct HdfDeviceNode *devNode, struct IPowerEventListener *listener); + struct HdfDeviceNode *devNode, const struct IPowerEventListener *listener); +void HdfDeviceNodeRemovePowerStateListener( + struct HdfDeviceNode *devNode, const struct IPowerEventListener *listener); void HdfDeviceNodeConstruct(struct HdfDeviceNode *service); void HdfDeviceNodeDestruct(struct HdfDeviceNode *service); struct HdfDeviceNode *HdfDeviceNodeNewInstance(void); diff --git a/core/host/include/hdf_driver_loader.h b/core/host/include/hdf_driver_loader.h index e6fbb413..56048807 100644 --- a/core/host/include/hdf_driver_loader.h +++ b/core/host/include/hdf_driver_loader.h @@ -25,10 +25,12 @@ struct HdfDriverLoader { }; struct HdfObject *HdfDriverLoaderCreate(void); +void HdfDriverLoaderConstruct(struct HdfDriverLoader *inst); void HdfDriverLoaderRelease(struct HdfObject *object); struct IDriverLoader *HdfDriverLoaderGetInstance(void); struct HdfDriverEntry *HdfDriverLoaderGetDriverEntry(const struct HdfDeviceInfo *deviceInfo); struct HdfDeviceNode *HdfDriverLoaderLoadNode( struct IDriverLoader *loader, const struct HdfDeviceInfo *deviceInfo); +void HdfDriverLoaderUnLoadNode(struct IDriverLoader *loader, const struct HdfDeviceInfo *deviceInfo); #endif /* HDF_DRIVER_LOADER_H */ diff --git a/core/host/include/power_state_token.h b/core/host/include/power_state_token.h index eda268bf..f82d0a22 100644 --- a/core/host/include/power_state_token.h +++ b/core/host/include/power_state_token.h @@ -11,17 +11,19 @@ #include "hdf_sref.h" #include "power_state_token_if.h" +#include "hdf_pm.h" struct PowerStateToken { struct IPowerStateToken super; - struct IPowerEventListener *listener; + const struct IPowerEventListener *listener; struct HdfDeviceObject *deviceObject; struct HdfSRef wakeRef; HdfPowerState state; + uint32_t mode; }; struct PowerStateToken *PowerStateTokenNewInstance( - struct HdfDeviceObject *deviceObject, struct IPowerEventListener *listener); + struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener); void PowerStateTokenFreeInstance(struct PowerStateToken *stateToken); - +int PowerStateOnSysStateChange(struct PowerStateToken *stateToken, int32_t state); #endif /* POWER_STATE_TOKEN_H */ \ No newline at end of file diff --git a/core/host/src/devhost_service.c b/core/host/src/devhost_service.c index 71f1ffd9..52cc5390 100644 --- a/core/host/src/devhost_service.c +++ b/core/host/src/devhost_service.c @@ -10,9 +10,7 @@ #include "devmgr_service_clnt.h" #include "devsvc_manager_clnt.h" #include "hdf_base.h" -#include "hdf_device_node_ext.h" #include "hdf_driver_loader.h" -#include "hdf_io_service.h" #include "hdf_log.h" #include "hdf_object_manager.h" #include "osal_mem.h" @@ -21,17 +19,13 @@ static struct HdfDevice *DevHostServiceFindDevice(struct DevHostService *inst, uint16_t deviceId) { - struct HdfSListIterator it; struct HdfDevice *deviceNode = NULL; if (inst == NULL) { - HDF_LOGE("Find driver failed, inst is null"); + HDF_LOGE("failed to find driver, inst is null"); return NULL; } - HdfSListIteratorInit(&it, &inst->devices); - while (HdfSListIteratorHasNext(&it)) { - deviceNode = (struct HdfDevice *)HDF_SLIST_CONTAINER_OF( - struct HdfSListNode, HdfSListIteratorNext(&it), struct HdfDevice, node); + DLIST_FOR_EACH_ENTRY(deviceNode, &inst->devices, struct HdfDevice, node) { if (deviceNode->deviceId == deviceId) { return deviceNode; } @@ -43,7 +37,7 @@ static void DevHostServiceFreeDevice(struct DevHostService *inst, uint16_t devic { struct HdfDevice *deviceNode = DevHostServiceFindDevice(inst, deviceId); if (deviceNode != NULL) { - HdfSListRemove(&inst->devices, &deviceNode->node); + DListRemove(&deviceNode->node); HdfDeviceFreeInstance(deviceNode); } } @@ -54,12 +48,12 @@ static struct HdfDevice *DevHostServiceGetDevice(struct DevHostService *inst, ui if (device == NULL) { device = HdfDeviceNewInstance(); if (device == NULL) { - HDF_LOGE("Dev host service create driver instance failed"); + HDF_LOGE("Dev host service failed to create driver instance"); return NULL; } device->hostId = inst->hostId; device->deviceId = deviceId; - HdfSListAdd(&inst->devices, &device->node); + DListInsertHead(&device->node, &inst->devices); } return device; } @@ -70,16 +64,16 @@ int DevHostServiceAddDevice(struct IDevHostService *inst, const struct HdfDevice struct HdfDevice *device = NULL; struct HdfDeviceNode *devNode = NULL; struct DevHostService *hostService = (struct DevHostService *)inst; - struct IDriverLoader *driverLoader = HdfDriverLoaderGetInstance(); + struct IDriverLoader *driverLoader = HdfDriverLoaderGetInstance(); if ((deviceInfo == NULL) || (driverLoader == NULL) || (driverLoader->LoadNode == NULL)) { - HDF_LOGE("Add device failed, input param is null"); + HDF_LOGE("failed to add device, input param is null"); return ret; } device = DevHostServiceGetDevice(hostService, deviceInfo->deviceId); - if (device == NULL || device->super.Attach == NULL) { - ret = HDF_DEV_ERR_NO_MEMORY; + if ((device == NULL) || (device->super.Attach == NULL)) { + ret = HDF_DEV_ERR_NO_DEVICE; goto error; } @@ -96,48 +90,58 @@ int DevHostServiceAddDevice(struct IDevHostService *inst, const struct HdfDevice return HDF_SUCCESS; error: - if (!HdfSListIsEmpty(&hostService->devices)) { - DevHostServiceFreeDevice(hostService, deviceInfo->deviceId); + if (DListIsEmpty(&hostService->devices)) { + DevHostServiceFreeDevice(hostService, hostService->hostId); } return ret; } -static int DevHostServiceDelDevice(struct IDevHostService *inst, const struct HdfDeviceInfo *deviceInfo) +static struct HdfDeviceNode *DevHostServiceGetDeviceNode(struct HdfSList *deviceNodes, + const struct HdfDeviceInfo *deviceInfo) +{ + struct HdfSListIterator it; + struct HdfDeviceNode *deviceNode = NULL; + HdfSListIteratorInit(&it, deviceNodes); + while (HdfSListIteratorHasNext(&it)) { + deviceNode = HDF_SLIST_CONTAINER_OF( + struct HdfSListNode, HdfSListIteratorNext(&it), struct HdfDeviceNode, entry); + if (strcmp(deviceNode->deviceInfo->svcName, deviceInfo->svcName) == 0 && + strcmp(deviceNode->deviceInfo->moduleName, deviceInfo->moduleName) == 0) { + HdfSListRemove(deviceNodes, &deviceNode->entry); + return deviceNode; + } + } + return NULL; +} + +int DevHostServiceDelDevice(struct IDevHostService *inst, const struct HdfDeviceInfo *deviceInfo) { struct HdfDevice *device = NULL; struct DevHostService *hostService = (struct DevHostService *)inst; struct IDriverLoader *driverLoader = HdfDriverLoaderGetInstance(); if ((deviceInfo == NULL) || (driverLoader == NULL) || (driverLoader->UnLoadNode == NULL)) { - HDF_LOGE("Add device failed, input param is null"); + HDF_LOGE("failed to del device, input param is null"); return HDF_FAILURE; } device = DevHostServiceGetDevice(hostService, deviceInfo->deviceId); if (device == NULL) { - HDF_LOGW("Del device failed, device is not exist"); + HDF_LOGW("failed to del device, device is not exist"); return HDF_SUCCESS; } driverLoader->UnLoadNode(driverLoader, deviceInfo); - struct HdfSListIterator it; - struct HdfDeviceNode *deviceNode = NULL; - HdfSListIteratorInit(&it, &device->services); - while (HdfSListIteratorHasNext(&it)) { - deviceNode = (struct HdfDeviceNode *)HDF_SLIST_CONTAINER_OF( - struct HdfSListNode, HdfSListIteratorNext(&it), struct HdfDeviceNode, entry); - if ((strcmp(deviceNode->deviceInfo->moduleName, deviceInfo->moduleName) == 0) && - (strcmp(deviceNode->deviceInfo->svcName, deviceInfo->svcName) == 0)) { - struct DeviceNodeExt *deviceNodeExt = (struct DeviceNodeExt *)deviceNode; - HdfSListRemove(&device->services, &deviceNode->entry); - DeviceNodeExtRelease(&deviceNodeExt->super.super.object); - } - } - - if (!HdfSListIsEmpty(&hostService->devices)) { - DevHostServiceFreeDevice(hostService, device->deviceId); + struct HdfDeviceNode *devNode = DevHostServiceGetDeviceNode(&device->services, deviceInfo); + if (device->super.Detach != NULL) { + device->super.Detach(&device->super, devNode); + } else { + HdfDeviceNodeFreeInstance(devNode); } DevSvcManagerClntRemoveService(deviceInfo->svcName); + if (HdfSListIsEmpty(&device->services)) { + DevHostServiceFreeDevice(hostService, device->deviceId); + } return HDF_SUCCESS; } @@ -145,7 +149,7 @@ static int DevHostServiceStartService(struct IDevHostService *service) { struct DevHostService *hostService = (struct DevHostService*)service; if (hostService == NULL) { - HDF_LOGE("Start device service failed, hostService is null"); + HDF_LOGE("failed to start device service, hostService is null"); return HDF_FAILURE; } return DevmgrServiceClntAttachDeviceHost(hostService->hostId, service); @@ -158,14 +162,22 @@ void DevHostServiceConstruct(struct DevHostService *service) hostServiceIf->AddDevice = DevHostServiceAddDevice; hostServiceIf->DelDevice = DevHostServiceDelDevice; hostServiceIf->StartService = DevHostServiceStartService; - HdfSListInit(&service->devices); + DListHeadInit(&service->devices); HdfServiceObserverConstruct(&service->observer); } } void DevHostServiceDestruct(struct DevHostService *service) { - HdfSListFlush(&service->devices, HdfDeviceDelete); + if (service == NULL) { + return; + } + + struct HdfDevice *device = NULL; + struct HdfDevice *tmp = NULL; + DLIST_FOR_EACH_ENTRY_SAFE(device, tmp, &service->devices, struct HdfDevice, node) { + HdfDeviceFreeInstance(device); + } HdfServiceObserverDestruct(&service->observer); } diff --git a/core/host/src/devmgr_service_clnt.c b/core/host/src/devmgr_service_clnt.c index 712e2098..378ec5f5 100644 --- a/core/host/src/devmgr_service_clnt.c +++ b/core/host/src/devmgr_service_clnt.c @@ -19,13 +19,13 @@ int DevmgrServiceClntAttachDeviceHost(uint16_t hostId, struct IDevHostService *h struct IDevmgrService *devMgrSvcIf = NULL; struct DevmgrServiceClnt *inst = DevmgrServiceClntGetInstance(); if ((inst == NULL) || (inst->devMgrSvcIf == NULL)) { - HDF_LOGE("Attach device host failed, get device manager service client is null"); + HDF_LOGE("failed to attach device host, get device manager service client is null"); return HDF_FAILURE; } devMgrSvcIf = inst->devMgrSvcIf; if (devMgrSvcIf->AttachDeviceHost == NULL) { - HDF_LOGE("Attach device host failed, attach device host function is null"); + HDF_LOGE("failed to attach device host, attach device host function is null"); return HDF_FAILURE; } return devMgrSvcIf->AttachDeviceHost(devMgrSvcIf, hostId, hostService); @@ -36,13 +36,13 @@ int DevmgrServiceClntAttachDevice(const struct HdfDeviceInfo *deviceInfo, struct struct IDevmgrService *devMgrSvcIf = NULL; struct DevmgrServiceClnt *inst = DevmgrServiceClntGetInstance(); if ((inst == NULL) || (inst->devMgrSvcIf == NULL)) { - HDF_LOGE("Device manager service client attach device failed, inst is null"); + HDF_LOGE("devmgr client failed to attach device, inst is null"); return HDF_FAILURE; } devMgrSvcIf = inst->devMgrSvcIf; if (devMgrSvcIf->AttachDevice == NULL) { - HDF_LOGE("Device manager service client attach device failed, dmsOps->AttachDevice is nul"); + HDF_LOGE("devmgr client failed to attach device, dmsOps->AttachDevice is nul"); return HDF_FAILURE; } return devMgrSvcIf->AttachDevice(devMgrSvcIf, deviceInfo, deviceToken); diff --git a/core/host/src/devsvc_manager_clnt.c b/core/host/src/devsvc_manager_clnt.c index e3ae2142..7dd4aef7 100644 --- a/core/host/src/devsvc_manager_clnt.c +++ b/core/host/src/devsvc_manager_clnt.c @@ -20,13 +20,13 @@ int DevSvcManagerClntAddService(const char *svcName, struct HdfDeviceObject *ser { struct DevSvcManagerClnt *devSvcMgrClnt = DevSvcManagerClntGetInstance(); if (devSvcMgrClnt == NULL) { - HDF_LOGE("Get device manager client is null"); + HDF_LOGE("failed to add service, client is null"); return HDF_FAILURE; } struct IDevSvcManager *serviceManager = devSvcMgrClnt->devSvcMgrIf; if (serviceManager == NULL || serviceManager->AddService == NULL) { - HDF_LOGE("AddService function is not assigned"); + HDF_LOGE("serviceManager AddService function is null"); return HDF_FAILURE; } return serviceManager->AddService(serviceManager, svcName, service); @@ -36,13 +36,13 @@ const struct HdfObject *DevSvcManagerClntGetService(const char *svcName) { struct DevSvcManagerClnt *devSvcMgrClnt = DevSvcManagerClntGetInstance(); if (devSvcMgrClnt == NULL) { - HDF_LOGE("Get device manager client is null"); + HDF_LOGE("failed to get service, client is null"); return NULL; } struct IDevSvcManager *serviceManager = devSvcMgrClnt->devSvcMgrIf; if (serviceManager == NULL || serviceManager->GetService == NULL) { - HDF_LOGE("GetService function is not assigned"); + HDF_LOGE("serviceManager GetService function is null"); return NULL; } return serviceManager->GetService(serviceManager, svcName); @@ -52,13 +52,13 @@ struct HdfDeviceObject *DevSvcManagerClntGetDeviceObject(const char *svcName) { struct DevSvcManagerClnt *devSvcMgrClnt = DevSvcManagerClntGetInstance(); if (devSvcMgrClnt == NULL) { - HDF_LOGE("Get device manager client is null"); + HDF_LOGE("failed to get device object, client is null"); return NULL; } struct IDevSvcManager *serviceManager = devSvcMgrClnt->devSvcMgrIf; if (serviceManager == NULL || serviceManager->GetObject == NULL) { - HDF_LOGE("GetObject function is not assigned"); + HDF_LOGE("failed to get device object, method not implement"); return NULL; } return serviceManager->GetObject(serviceManager, svcName); @@ -82,10 +82,8 @@ struct HdfDeviceObject *HdfRegisterDevice(const char *moduleName, const char *se void HdfUnregisterDevice(const char *moduleName, const char *serviceName) { - int ret; - ret = DevmgrServiceUnLoadDevice(serviceName); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s unload device %s failed!", __func__, serviceName); + if (DevmgrServiceUnLoadDevice(serviceName) != HDF_SUCCESS) { + HDF_LOGE("%s:failed to unload device %s !", __func__, serviceName); } HdfDeviceListDel(moduleName, serviceName); } @@ -94,13 +92,13 @@ int DevSvcManagerClntSubscribeService(const char *svcName, struct SubscriberCall { struct DevSvcManagerClnt *devSvcMgrClnt = DevSvcManagerClntGetInstance(); if (devSvcMgrClnt == NULL) { - HDF_LOGE("Get device manager client is null"); + HDF_LOGE("failed to subscribe service, client is null"); return HDF_FAILURE; } struct IDevSvcManager *serviceManager = devSvcMgrClnt->devSvcMgrIf; if (serviceManager == NULL || serviceManager->SubscribeService == NULL) { - HDF_LOGE("SubscribeService function is not assigned"); + HDF_LOGE("failed to subscribe service, method not implement"); return HDF_FAILURE; } return serviceManager->SubscribeService(serviceManager, svcName, callback); @@ -110,13 +108,13 @@ int DevSvcManagerClntUnsubscribeService(const char *svcName) { struct DevSvcManagerClnt *devSvcMgrClnt = DevSvcManagerClntGetInstance(); if (devSvcMgrClnt == NULL) { - HDF_LOGE("Get device manager client is null"); + HDF_LOGE("failed to unsubscribe service, client is null"); return HDF_FAILURE; } struct IDevSvcManager *serviceManager = devSvcMgrClnt->devSvcMgrIf; if (serviceManager == NULL || serviceManager->UnsubscribeService == NULL) { - HDF_LOGE("UnsubService function is not assigned"); + HDF_LOGE("failed to unsubscribe service, method not implement"); return HDF_FAILURE; } return serviceManager->UnsubscribeService(serviceManager, svcName); @@ -126,13 +124,13 @@ void DevSvcManagerClntRemoveService(const char *svcName) { struct DevSvcManagerClnt *devSvcMgrClnt = DevSvcManagerClntGetInstance(); if (devSvcMgrClnt == NULL) { - HDF_LOGE("Get device manager client is null"); + HDF_LOGE("failed to remove service, devSvcMgrClnt is null"); return; } struct IDevSvcManager *serviceManager = devSvcMgrClnt->devSvcMgrIf; if (serviceManager == NULL || serviceManager->RemoveService == NULL) { - HDF_LOGE("Remove service function is not assigned"); + HDF_LOGE("failed to remove service, method not implement"); return; } serviceManager->RemoveService(serviceManager, svcName); @@ -157,9 +155,7 @@ struct DevSvcManagerClnt *DevSvcManagerClntGetInstance() void DevSvcManagerClntFreeInstance(struct DevSvcManagerClnt *instance) { if (instance != NULL) { - if (instance->devSvcMgrIf != NULL) { - HdfObjectManagerFreeObject((struct HdfObject *)instance->devSvcMgrIf); - } + HdfObjectManagerFreeObject((struct HdfObject *)instance->devSvcMgrIf); } } diff --git a/core/host/src/hdf_device.c b/core/host/src/hdf_device.c index b4f27d19..3fc55700 100644 --- a/core/host/src/hdf_device.c +++ b/core/host/src/hdf_device.c @@ -23,7 +23,7 @@ static int HdfDeviceAttach(struct IHdfDevice *devInst, struct HdfDeviceNode *dev struct HdfDevice *device = (struct HdfDevice *)devInst; struct IDeviceNode *nodeIf = (struct IDeviceNode *)devNode; if (device == NULL || nodeIf == NULL || nodeIf->LaunchNode == NULL) { - HDF_LOGE("Device attach failed, input params is wrong"); + HDF_LOGE("failed to attach device, input params invalid"); return HDF_ERR_INVALID_PARAM; } HdfSListAdd(&device->services, &devNode->entry); diff --git a/core/host/src/hdf_device_node.c b/core/host/src/hdf_device_node.c index 4ccd58a1..793da0d6 100644 --- a/core/host/src/hdf_device_node.c +++ b/core/host/src/hdf_device_node.c @@ -26,12 +26,12 @@ static int HdfDeviceNodePublishLocalService( { uint32_t matchId; if ((devNode == NULL) || (deviceInfo == NULL)) { - HDF_LOGE("Publish local service failed, device is null"); + HDF_LOGE("failed to publish local service, device is null"); return HDF_FAILURE; } struct DevHostService *hostService = devNode->hostService; if (hostService == NULL) { - HDF_LOGE("Publish local service failed, host service is null"); + HDF_LOGE("failed to publish local service, host service is null"); return HDF_FAILURE; } matchId = HdfMakeHardwareId(deviceInfo->hostId, deviceInfo->deviceId); @@ -44,7 +44,8 @@ static int HdfDeviceNodePublishService( { (void)device; int status = HDF_SUCCESS; - if (deviceInfo->policy == SERVICE_POLICY_NONE) { + if ((deviceInfo->policy == SERVICE_POLICY_NONE) || + ((deviceInfo->svcName != NULL) && (strlen(deviceInfo->svcName) == 0))) { HDF_LOGI("policy is %d", SERVICE_POLICY_NONE); return status; } @@ -66,7 +67,7 @@ int HdfDeviceLaunchNode(struct HdfDeviceNode *devNode, struct IHdfDevice *devIns { struct HdfDevice *device = (struct HdfDevice *)devInst; if (device == NULL || devNode == NULL) { - HDF_LOGE("Launch service failed, device or service is null"); + HDF_LOGE("failed to launch service, device or service is null"); return HDF_ERR_INVALID_PARAM; } @@ -75,12 +76,12 @@ int HdfDeviceLaunchNode(struct HdfDeviceNode *devNode, struct IHdfDevice *devIns struct IHdfDeviceToken *deviceToken = NULL; if (deviceInfo == NULL) { - HDF_LOGE("Launch service failed, deviceInfo is null"); + HDF_LOGE("failed to launch service, deviceInfo is null"); return HDF_ERR_INVALID_PARAM; } if ((driverEntry == NULL) || (driverEntry->Init == NULL)) { - HDF_LOGE("deviceEntry or deviceEntry->Init is null"); + HDF_LOGE("failed to launch service, deviceEntry invalid"); return HDF_ERR_INVALID_PARAM; } int ret = driverEntry->Init(&devNode->deviceObject); @@ -109,21 +110,33 @@ int HdfDeviceLaunchNode(struct HdfDeviceNode *devNode, struct IHdfDevice *devIns } int HdfDeviceNodeAddPowerStateListener( - struct HdfDeviceNode *devNode, struct IPowerEventListener *listener) + struct HdfDeviceNode *devNode, const struct IPowerEventListener *listener) { if (devNode->powerToken != NULL) { return HDF_FAILURE; } - if (devNode->powerToken == NULL) { - devNode->powerToken = PowerStateTokenNewInstance(&devNode->deviceObject, listener); - } + + devNode->powerToken = PowerStateTokenNewInstance(&devNode->deviceObject, listener); return (devNode->powerToken != NULL) ? HDF_SUCCESS : HDF_FAILURE; } +void HdfDeviceNodeRemovePowerStateListener( + struct HdfDeviceNode *devNode, const struct IPowerEventListener *listener) +{ + (void)listener; + if (devNode == NULL || devNode->powerToken == NULL) { + return; + } + + PowerStateTokenFreeInstance(devNode->powerToken); + devNode->powerToken = NULL; +} + + int HdfDeviceNodePublishPublicService(struct HdfDeviceNode *devNode, const char *svcName) { if ((devNode == NULL) || (devNode->deviceObject.service == NULL)) { - HDF_LOGE("device method is null"); + HDF_LOGE("failed to publish public service: devNode is NULL"); return HDF_FAILURE; } return DevSvcManagerClntAddService(svcName, &devNode->deviceObject); diff --git a/core/host/src/hdf_device_object.c b/core/host/src/hdf_device_object.c index 2c109ac3..832b11d8 100644 --- a/core/host/src/hdf_device_object.c +++ b/core/host/src/hdf_device_object.c @@ -23,19 +23,19 @@ int32_t HdfDeviceSubscribeService( struct DevHostService *hostService = NULL; const struct HdfDeviceInfo *deviceInfo = NULL; if (deviceObject == NULL || serviceName == NULL) { - HDF_LOGE("%s input param is invalid", __func__); + HDF_LOGE("failed to subscribe service, deviceObject/serviceName is null"); return HDF_FAILURE; } struct HdfDeviceNode *devNode = (struct HdfDeviceNode *)HDF_SLIST_CONTAINER_OF( struct HdfDeviceObject, deviceObject, struct HdfDeviceNode, deviceObject); hostService = devNode->hostService; if (hostService == NULL) { - HDF_LOGE("Get host service is null"); + HDF_LOGE("failed to subscribe service, hostService is null"); return HDF_FAILURE; } deviceInfo = devNode->deviceInfo; if (deviceInfo == NULL) { - HDF_LOGE("Get device deviceInfo is null"); + HDF_LOGE("failed to subscribe service, deviceInfo is null"); return HDF_FAILURE; } matchId = HdfMakeHardwareId(deviceInfo->hostId, deviceInfo->deviceId); @@ -45,34 +45,43 @@ int32_t HdfDeviceSubscribeService( const char *HdfDeviceGetServiceName(const struct HdfDeviceObject *deviceObject) { if (deviceObject == NULL) { - HDF_LOGE("%s input param is invalid", __func__); + HDF_LOGE("failed to get service name, deviceObject is invalid"); return NULL; } struct HdfDeviceNode *devNode = (struct HdfDeviceNode *)HDF_SLIST_CONTAINER_OF( struct HdfDeviceObject, deviceObject, struct HdfDeviceNode, deviceObject); const struct HdfDeviceInfo *deviceInfo = devNode->deviceInfo; if (deviceInfo == NULL) { - HDF_LOGE("Get device deviceInfo is null"); + HDF_LOGE("failed to get service name, deviceInfo is null"); return NULL; } return deviceInfo->svcName; } -void HdfDeviceRegisterPowerListener(struct HdfDeviceObject *deviceObject, struct IPowerEventListener *listener) +int HdfPmRegisterPowerListener(struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener) +{ + if (deviceObject == NULL) { + return HDF_ERR_INVALID_PARAM; + } + struct HdfDeviceNode *devNode = (struct HdfDeviceNode *)HDF_SLIST_CONTAINER_OF( + struct HdfDeviceObject, deviceObject, struct HdfDeviceNode, deviceObject); + return HdfDeviceNodeAddPowerStateListener(devNode, listener); +} + +void HdfPmUnregisterPowerListener(struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener) { if (deviceObject == NULL) { - HDF_LOGE("%s input param is invalid", __func__); return; } struct HdfDeviceNode *devNode = (struct HdfDeviceNode *)HDF_SLIST_CONTAINER_OF( struct HdfDeviceObject, deviceObject, struct HdfDeviceNode, deviceObject); - HdfDeviceNodeAddPowerStateListener(devNode, listener); + HdfDeviceNodeRemovePowerStateListener(devNode, listener); } -void HdfDeviceAcquireWakeLock(struct HdfDeviceObject *deviceObject) +void HdfPmAcquireDevice(struct HdfDeviceObject *deviceObject) { if (deviceObject == NULL) { - HDF_LOGE("%s input param is invalid", __func__); + HDF_LOGE("%s: input param is invalid", __func__); return; } struct HdfDeviceNode *devNode = (struct HdfDeviceNode *)HDF_SLIST_CONTAINER_OF( @@ -83,10 +92,10 @@ void HdfDeviceAcquireWakeLock(struct HdfDeviceObject *deviceObject) } } -void HdfDeviceReleaseWakeLock(struct HdfDeviceObject *deviceObject) +void HdfPmReleaseDevice(struct HdfDeviceObject *deviceObject) { if (deviceObject == NULL) { - HDF_LOGE("%s input param is invalid", __func__); + HDF_LOGE("%s: input param is invalid", __func__); return; } struct HdfDeviceNode *devNode = (struct HdfDeviceNode *)HDF_SLIST_CONTAINER_OF( @@ -97,6 +106,20 @@ void HdfDeviceReleaseWakeLock(struct HdfDeviceObject *deviceObject) } } +void HdfPmSetMode(struct HdfDeviceObject *deviceObject, uint32_t mode) +{ + if (deviceObject == NULL || mode > HDF_POWER_MODE_MAX) { + HDF_LOGE("%s: input param is invalid", __func__); + return; + } + struct HdfDeviceNode *devNode = (struct HdfDeviceNode *)HDF_SLIST_CONTAINER_OF( + struct HdfDeviceObject, deviceObject, struct HdfDeviceNode, deviceObject); + struct PowerStateToken *token = devNode->powerToken; + if (token != NULL) { + token->mode = mode; + } +} + bool HdfDeviceSetClass(struct HdfDeviceObject *deviceObject, DeviceClass deviceClass) { if ((deviceObject == NULL) || (deviceClass >= DEVICE_CLASS_MAX) || diff --git a/core/host/src/hdf_driver_loader.c b/core/host/src/hdf_driver_loader.c old mode 100644 new mode 100755 index ec9f7801..5ef03def --- a/core/host/src/hdf_driver_loader.c +++ b/core/host/src/hdf_driver_loader.c @@ -23,27 +23,28 @@ struct HdfDeviceNode *HdfDriverLoaderLoadNode( struct HdfDriverEntry *driverEntry = NULL; struct HdfDeviceNode *devNode = NULL; if ((loader == NULL) || (loader->GetDriverEntry == NULL)) { - HDF_LOGE("loader or loader->GetDriverEntry is null"); + HDF_LOGE("failed to load node, loader is invalid"); return NULL; } driverEntry = loader->GetDriverEntry(deviceInfo); if (driverEntry == NULL) { - HDF_LOGE("Load service failed, deviceEntry is null"); + HDF_LOGE("failed to load node, deviceEntry is null"); return NULL; } devNode = HdfDeviceNodeNewInstance(); if (devNode == NULL) { - HDF_LOGE("Load service failed, device node is null"); + HDF_LOGE("failed to load node, device node is null"); return NULL; } devNode->driverEntry = driverEntry; devNode->deviceInfo = deviceInfo; devNode->deviceObject.property = HcsGetNodeByMatchAttr(HdfGetRootNode(), deviceInfo->deviceMatchAttr); + if (devNode->deviceObject.property == NULL) { - HDF_LOGW("Get property is null, match attr is: %s", deviceInfo->deviceMatchAttr); + HDF_LOGW("failed to load node, property is null, match attr is: %s", deviceInfo->deviceMatchAttr); } if ((deviceInfo->policy == SERVICE_POLICY_PUBLIC) || (deviceInfo->policy == SERVICE_POLICY_CAPACITY)) { @@ -61,34 +62,38 @@ struct HdfDeviceNode *HdfDriverLoaderLoadNode( return devNode; } -static void HdfDriverLoaderUnLoadNode(struct IDriverLoader *loader, const struct HdfDeviceInfo *deviceInfo) +void HdfDriverLoaderUnLoadNode(struct IDriverLoader *loader, const struct HdfDeviceInfo *deviceInfo) { struct HdfDriverEntry *driverEntry = NULL; struct HdfDeviceObject *deviceObject = NULL; if ((loader == NULL) || (loader->GetDriverEntry == NULL)) { - HDF_LOGE("loader or loader->GetDriverEntry is null"); + HDF_LOGE("failed to unload service, loader invalid"); return; } driverEntry = loader->GetDriverEntry(deviceInfo); if (driverEntry == NULL) { - HDF_LOGE("Load service failed, driverEntry is null"); + HDF_LOGE("failed to unload service, driverEntry is null"); return; } if (driverEntry->Release == NULL) { - HDF_LOGI("Device Release func is null"); + HDF_LOGI("device release func is null"); return; } deviceObject = DevSvcManagerClntGetDeviceObject(deviceInfo->svcName); - driverEntry->Release(deviceObject); + if (deviceObject != NULL) { + driverEntry->Release(deviceObject); + } } -static void HdfDriverLoaderConstruct(struct HdfDriverLoader *inst) +void HdfDriverLoaderConstruct(struct HdfDriverLoader *inst) { - struct IDriverLoader *driverLoaderIf = (struct IDriverLoader *)inst; - driverLoaderIf->LoadNode = HdfDriverLoaderLoadNode; - driverLoaderIf->UnLoadNode = HdfDriverLoaderUnLoadNode; - driverLoaderIf->GetDriverEntry = HdfDriverLoaderGetDriverEntry; + if (inst != NULL) { + struct IDriverLoader *driverLoaderIf = (struct IDriverLoader *)inst; + driverLoaderIf->LoadNode = HdfDriverLoaderLoadNode; + driverLoaderIf->UnLoadNode = HdfDriverLoaderUnLoadNode; + driverLoaderIf->GetDriverEntry = HdfDriverLoaderGetDriverEntry; + } } struct HdfObject *HdfDriverLoaderCreate() diff --git a/core/host/src/hdf_observer_record.c b/core/host/src/hdf_observer_record.c index d75f5c95..645d7d54 100644 --- a/core/host/src/hdf_observer_record.c +++ b/core/host/src/hdf_observer_record.c @@ -16,9 +16,7 @@ uint32_t HdfMakeHardwareId(uint16_t hostId, uint16_t deviceId) { - uint32_t hardwareId = hostId; - hardwareId = (hardwareId << HALF_INT_LEN) | deviceId; - return hardwareId; + return ((uint32_t)hostId << HALF_INT_LEN) | deviceId; } struct HdfServiceObserverRecord *HdfServiceObserverRecordObtain(uint32_t serviceKey) diff --git a/core/host/src/hdf_service_observer.c b/core/host/src/hdf_service_observer.c index 52bafee2..29aa1555 100644 --- a/core/host/src/hdf_service_observer.c +++ b/core/host/src/hdf_service_observer.c @@ -32,7 +32,6 @@ void HdfServiceObserverDestruct(struct HdfServiceObserver *observer) if (observer != NULL) { HdfSListFlush(&observer->services, HdfServiceObserverRecordDelete); OsalMutexDestroy(&observer->observerMutex); - observer->observerMutex.realMutex = NULL; } } @@ -51,20 +50,22 @@ int HdfServiceObserverSubscribeService(struct HdfServiceObserver *observer, if (serviceRecord == NULL) { serviceRecord = HdfServiceObserverRecordObtain(serviceKey); if (serviceRecord == NULL) { - HDF_LOGE("SubscribeService failed, serviceRecord is null"); + HDF_LOGE("failed to subscribe service, serviceRecord is null"); return HDF_FAILURE; } subscriber = HdfServiceSubscriberObtain(callback, matchId); if (subscriber == NULL) { - HDF_LOGE("SubscribeService failed, subscriber is null"); + HDF_LOGE("failed to subscribe service, subscriber is null"); HdfServiceObserverRecordRecycle(serviceRecord); return HDF_FAILURE; } + OsalMutexLock(&observer->observerMutex); HdfSListAdd(&observer->services, &serviceRecord->entry); + OsalMutexUnlock(&observer->observerMutex); } else { subscriber = HdfServiceSubscriberObtain(callback, matchId); if (subscriber == NULL) { - HDF_LOGE("SubscribeService failed, hdf search list is null, subscriber is null"); + HDF_LOGE("failed to subscribe service, subscriber obtain null"); return HDF_FAILURE; } } @@ -101,7 +102,9 @@ int HdfServiceObserverPublishService(struct HdfServiceObserver *observer, serviceRecord->publisher = service; serviceRecord->matchId = matchId; serviceRecord->policy = policy; + OsalMutexLock(&observer->observerMutex); HdfSListAdd(&observer->services, &serviceRecord->entry); + OsalMutexUnlock(&observer->observerMutex); } else { serviceRecord->publisher = service; HdfServiceObserverRecordNotifySubscribers(serviceRecord, matchId, policy); diff --git a/core/host/src/hdf_service_subscriber.c b/core/host/src/hdf_service_subscriber.c index 6307977e..efcec2f4 100644 --- a/core/host/src/hdf_service_subscriber.c +++ b/core/host/src/hdf_service_subscriber.c @@ -6,8 +6,8 @@ * See the LICENSE file in the root of this repository for complete details. */ -#include "osal_mem.h" #include "hdf_service_subscriber.h" +#include "osal_mem.h" struct HdfServiceSubscriber *HdfServiceSubscriberObtain(struct SubscriberCallback callback, uint32_t matchId) { diff --git a/core/host/src/power_state_token.c b/core/host/src/power_state_token.c index 41702590..ab65bbf6 100644 --- a/core/host/src/power_state_token.c +++ b/core/host/src/power_state_token.c @@ -11,12 +11,110 @@ #include "hdf_device_desc.h" #include "hdf_slist.h" #include "osal_mem.h" +#include "osal_sysevent.h" -static void PowerStateTokenAcqureWakeLock(struct IPowerStateToken *token) +static void PowerStateTokenOnFirstAcquire(struct HdfSRef *sref) +{ + if (sref == NULL) { + return; + } + struct PowerStateToken *stateToken = (struct PowerStateToken *)HDF_SLIST_CONTAINER_OF( + struct HdfSRef, sref, struct PowerStateToken, wakeRef); + + if (stateToken->state == POWER_STATE_ACTIVE) { + return; + } + + struct IDevmgrService *devMgrSvcIf = NULL; + struct DevmgrServiceClnt *inst = DevmgrServiceClntGetInstance(); + if (inst == NULL) { + return; + } + devMgrSvcIf = (struct IDevmgrService *)inst->devMgrSvcIf; + if (devMgrSvcIf != NULL && devMgrSvcIf->AcquireWakeLock != NULL) { + devMgrSvcIf->AcquireWakeLock(devMgrSvcIf, &stateToken->super); + } + + if (stateToken->state == POWER_STATE_INACTIVE || stateToken->state == POWER_STATE_IDLE) { + const struct IPowerEventListener *listener = stateToken->listener; + if ((listener != NULL) && (listener->Resume != NULL)) { + listener->Resume(stateToken->deviceObject); + } + } + stateToken->state = POWER_STATE_ACTIVE; +} + +static void PowerStateTokenOnLastRelease(struct HdfSRef *sref) +{ + if (sref == NULL) { + return; + } + struct PowerStateToken *stateToken = (struct PowerStateToken *)HDF_SLIST_CONTAINER_OF( + struct HdfSRef, sref, struct PowerStateToken, wakeRef); + + if (stateToken->state != POWER_STATE_ACTIVE && stateToken->state != POWER_STATE_IDLE) { + return; + } + + struct IDevmgrService *devMgrSvcIf = NULL; + const struct IPowerEventListener *listener = stateToken->listener; + struct DevmgrServiceClnt *inst = DevmgrServiceClntGetInstance(); + if (inst == NULL) { + return; + } + + if (stateToken->state == POWER_STATE_ACTIVE) { + devMgrSvcIf = (struct IDevmgrService *)inst->devMgrSvcIf; + if ((devMgrSvcIf != NULL) && (devMgrSvcIf->AcquireWakeLock != NULL)) { + devMgrSvcIf->ReleaseWakeLock(devMgrSvcIf, &stateToken->super); + } + } + + if ((listener != NULL) && (listener->Suspend != NULL)) { + listener->Suspend(stateToken->deviceObject); + } + stateToken->state = POWER_STATE_INACTIVE; +} + +int PowerStateOnSysStateChange(struct PowerStateToken *stateToken, int32_t state) +{ + if (stateToken == NULL || stateToken->listener == NULL || stateToken->mode != HDF_POWER_SYS_CTRL) { + return HDF_SUCCESS; + } + + switch (state) { + case KEVENT_POWER_SUSPEND: + if (stateToken->listener->Suspend != NULL) { + return stateToken->listener->Suspend(stateToken->deviceObject); + } + break; + case KEVENT_POWER_RESUME: + if (stateToken->listener->Resume != NULL) { + return stateToken->listener->Resume(stateToken->deviceObject); + } + break; + case KEVENT_POWER_DISPLAY_OFF: + if (stateToken->listener->DozeSuspend != NULL) { + return stateToken->listener->DozeSuspend(stateToken->deviceObject); + } + break; + case KEVENT_POWER_DISPLAY_ON: + if (stateToken->listener->DozeResume != NULL) { + return stateToken->listener->DozeResume(stateToken->deviceObject); + } + break; + default: + break; + } + + return HDF_SUCCESS; +} + +static void PowerStateTokenAcquireWakeLock(struct IPowerStateToken *token) { struct HdfSRef *sref = NULL; struct PowerStateToken *stateToken = (struct PowerStateToken *)token; - if (stateToken == NULL) { + if (stateToken == NULL || stateToken->mode != HDF_POWER_DYNAMIC_CTRL) { return; } sref = (struct HdfSRef *)&stateToken->wakeRef; @@ -29,79 +127,32 @@ static void PowerStateTokenReleaseWakeLock(struct IPowerStateToken *token) { struct HdfSRef *sref = NULL; struct PowerStateToken *stateToken = (struct PowerStateToken *)token; - if (stateToken == NULL) { + if (stateToken == NULL || stateToken->mode != HDF_POWER_DYNAMIC_CTRL) { return; } sref = (struct HdfSRef *)&stateToken->wakeRef; - if ((sref != NULL) && (sref->Release != NULL)) { + if ((sref == NULL) || (sref->Release == NULL)) { + return; + } + + /* Not allowed to decrease the ref count to negative */ + if (HdfSRefCount(sref) == 0) { + PowerStateTokenOnLastRelease(sref); + } else { sref->Release(sref); } } -static void PowerStateTokenOnFirstAcquire(struct HdfSRef *sref) -{ - if (sref == NULL) { - return; - } - struct PowerStateToken *stateToken = (struct PowerStateToken *)HDF_SLIST_CONTAINER_OF( - struct HdfSRef, sref, struct PowerStateToken, wakeRef); - if (stateToken->state != POWER_STATE_ACTIVE) { - struct IDevmgrService *devMgrSvcIf = NULL; - struct IPowerEventListener* listener = stateToken->listener; - struct DevmgrServiceClnt *inst = DevmgrServiceClntGetInstance(); - if (inst == NULL) { - return; - } - devMgrSvcIf = (struct IDevmgrService *)inst->devMgrSvcIf; - if (devMgrSvcIf == NULL || devMgrSvcIf->AcquireWakeLock == NULL) { - return; - } - devMgrSvcIf->AcquireWakeLock(devMgrSvcIf, &stateToken->super); - if (stateToken->state == POWER_STATE_INACTIVE) { - if ((listener != NULL) && (listener->Resume != NULL)) { - listener->Resume(stateToken->deviceObject); - } - } - stateToken->state = POWER_STATE_ACTIVE; - } -} - -static void PowerStateTokenOnLastRelease(struct HdfSRef *sref) -{ - if (sref == NULL) { - return; - } - struct PowerStateToken *stateToken = (struct PowerStateToken *)HDF_SLIST_CONTAINER_OF( - struct HdfSRef, sref, struct PowerStateToken, wakeRef); - if (stateToken->state == POWER_STATE_ACTIVE) { - struct IDevmgrService *devMgrSvcIf = NULL; - struct IPowerEventListener *listener = stateToken->listener; - struct DevmgrServiceClnt *inst = DevmgrServiceClntGetInstance(); - if (inst == NULL) { - return; - } - devMgrSvcIf = (struct IDevmgrService *)inst->devMgrSvcIf; - if ((devMgrSvcIf == NULL) || (devMgrSvcIf->AcquireWakeLock == NULL)) { - return; - } - devMgrSvcIf->ReleaseWakeLock(devMgrSvcIf, &stateToken->super); - if ((listener != NULL) && (listener->Suspend != NULL)) { - listener->Suspend(stateToken->deviceObject); - } - stateToken->state = POWER_STATE_INACTIVE; - } -} - -static void PowerStateTokenConstruct( - struct PowerStateToken *powerStateToken, struct HdfDeviceObject *deviceObject, struct IPowerEventListener *listener) +static int32_t PowerStateTokenConstruct(struct PowerStateToken *powerStateToken, + struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener) { struct IPowerStateToken *tokenIf = &powerStateToken->super; struct IHdfSRefListener *srefListener = (struct IHdfSRefListener *)OsalMemCalloc(sizeof(struct IHdfSRefListener)); if (srefListener == NULL) { - return; + return HDF_ERR_MALLOC_FAIL; } - tokenIf->AcquireWakeLock = PowerStateTokenAcqureWakeLock; + tokenIf->AcquireWakeLock = PowerStateTokenAcquireWakeLock; tokenIf->ReleaseWakeLock = PowerStateTokenReleaseWakeLock; srefListener->OnFirstAcquire = PowerStateTokenOnFirstAcquire; @@ -111,16 +162,24 @@ static void PowerStateTokenConstruct( powerStateToken->listener = listener; powerStateToken->deviceObject = deviceObject; HdfSRefConstruct(&powerStateToken->wakeRef, srefListener); + + return HDF_SUCCESS; } struct PowerStateToken *PowerStateTokenNewInstance( - struct HdfDeviceObject *deviceObject, struct IPowerEventListener *listener) + struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener) { struct PowerStateToken *stateToken = (struct PowerStateToken *)OsalMemCalloc(sizeof(struct PowerStateToken)); - if (stateToken != NULL) { - PowerStateTokenConstruct(stateToken, deviceObject, listener); + if (stateToken == NULL) { + return NULL; } + + if (PowerStateTokenConstruct(stateToken, deviceObject, listener) != HDF_SUCCESS) { + OsalMemFree(stateToken); + return NULL; + } + return stateToken; } diff --git a/core/manager/include/devhost_service_clnt.h b/core/manager/include/devhost_service_clnt.h index 3a641297..c80f3b1c 100644 --- a/core/manager/include/devhost_service_clnt.h +++ b/core/manager/include/devhost_service_clnt.h @@ -11,11 +11,13 @@ #include "devhost_service_if.h" #include "hdf_slist.h" +#include "hdf_map.h" struct DevHostServiceClnt { struct HdfSListNode node; struct HdfSList devices; struct HdfSList *deviceInfos; + Map *deviceHashMap; struct IDevHostService *hostService; uint16_t devCount; uint16_t hostId; @@ -25,7 +27,7 @@ struct DevHostServiceClnt { int DevHostServiceClntInstallDriver(struct DevHostServiceClnt *hostClnt); struct DevHostServiceClnt *DevHostServiceClntNewInstance(uint16_t hostId, const char *hostName); -void DevHostServiceClntFreeInstance(struct DevHostServiceClnt* hostClnt); +void DevHostServiceClntFreeInstance(struct DevHostServiceClnt *hostClnt); void DevHostServiceClntDelete(struct HdfSListNode *listEntry); #endif /* DEVHOST_SERVICE_CLNT_H */ diff --git a/core/manager/include/devsvc_manager.h b/core/manager/include/devsvc_manager.h index 658fd49e..b73731bc 100644 --- a/core/manager/include/devsvc_manager.h +++ b/core/manager/include/devsvc_manager.h @@ -29,4 +29,7 @@ int DevSvcManagerAddService(struct IDevSvcManager *manager, const char *svcName, struct HdfObject *DevSvcManagerGetService(struct IDevSvcManager *manager, const char *svcName); void DevSvcManagerRemoveService(struct IDevSvcManager *manager, const char *svcName); +int DevSvcManagerClntSubscribeService(const char *svcName, struct SubscriberCallback callback); +int DevSvcManagerClntUnsubscribeService(const char *svcName); + #endif /* DEVICE_SERVICE_MANAGER_H */ diff --git a/core/manager/include/power_state_token_clnt.h b/core/manager/include/power_state_token_clnt.h index ba700d8b..1915a985 100644 --- a/core/manager/include/power_state_token_clnt.h +++ b/core/manager/include/power_state_token_clnt.h @@ -16,7 +16,7 @@ struct PowerStateTokenClnt { struct HdfSListNode entry; HdfPowerState powerState; - struct IPowerStateToken* tokenIf; + struct IPowerStateToken *tokenIf; }; struct PowerStateTokenClnt *PowerStateTokenClntNewInstance(struct IPowerStateToken *tokenIf); diff --git a/core/manager/src/devhost_service_clnt.c b/core/manager/src/devhost_service_clnt.c index ee31bab4..490cf040 100644 --- a/core/manager/src/devhost_service_clnt.c +++ b/core/manager/src/devhost_service_clnt.c @@ -23,7 +23,7 @@ int DevHostServiceClntInstallDriver(struct DevHostServiceClnt *hostClnt) struct HdfDeviceInfo *deviceInfo = NULL; struct IDevHostService *devHostSvcIf = NULL; if (hostClnt == NULL) { - HDF_LOGE("Install driver failed, hostClnt is null"); + HDF_LOGE("failed to install driver, hostClnt is null"); return HDF_FAILURE; } @@ -44,7 +44,7 @@ int DevHostServiceClntInstallDriver(struct DevHostServiceClnt *hostClnt) } ret = devHostSvcIf->AddDevice(devHostSvcIf, deviceInfo); if (ret != HDF_SUCCESS) { - HDF_LOGE("Install %s driver failed, ret = %d", deviceInfo->svcName, ret); + HDF_LOGE("failed to install driver %s, ret = %d", deviceInfo->svcName, ret); } } return HDF_SUCCESS; @@ -53,6 +53,12 @@ int DevHostServiceClntInstallDriver(struct DevHostServiceClnt *hostClnt) static void DevHostServiceClntConstruct(struct DevHostServiceClnt *hostClnt) { HdfSListInit(&hostClnt->devices); + hostClnt->deviceHashMap = (Map *)OsalMemCalloc(sizeof(Map)); + if (hostClnt->deviceHashMap == NULL) { + HDF_LOGE("%s:failed to malloc deviceHashMap", __func__); + return; + } + MapInit(hostClnt->deviceHashMap); } struct DevHostServiceClnt *DevHostServiceClntNewInstance(uint16_t hostId, const char *hostName) @@ -73,6 +79,7 @@ void DevHostServiceClntFreeInstance(struct DevHostServiceClnt *hostClnt) if (hostClnt != NULL) { HdfSListFlush(&hostClnt->devices, DeviceTokenClntDelete); HdfSListFlush(hostClnt->deviceInfos, HdfDeviceInfoDelete); + OsalMemFree(hostClnt->deviceHashMap); OsalMemFree(hostClnt); } } diff --git a/core/manager/src/device_token_clnt.c b/core/manager/src/device_token_clnt.c index e912a5c8..6d50b1b2 100644 --- a/core/manager/src/device_token_clnt.c +++ b/core/manager/src/device_token_clnt.c @@ -23,7 +23,7 @@ struct DeviceTokenClnt *DeviceTokenClntNewInstance(struct IHdfDeviceToken *token { struct DeviceTokenClnt *tokenClnt = NULL; if (tokenIf == NULL) { - HDF_LOGE("New token client failed, tokenIf is null"); + HDF_LOGE("failed to create token client, tokenIf is null"); return NULL; } tokenClnt = (struct DeviceTokenClnt *)OsalMemCalloc(sizeof(struct DeviceTokenClnt)); diff --git a/core/manager/src/devmgr_service.c b/core/manager/src/devmgr_service.c index 3472cf9e..545d8675 100644 --- a/core/manager/src/devmgr_service.c +++ b/core/manager/src/devmgr_service.c @@ -17,12 +17,15 @@ #include "hdf_object_manager.h" #include "power_state_manager.h" - #define HDF_LOG_TAG devmgr_service static int DevmgrServiceActiveDevice(struct DevHostServiceClnt *hostClnt, struct HdfDeviceInfo *deviceInfo, bool isLoad) { struct IDevHostService *devHostSvcIf = (struct IDevHostService *)hostClnt->hostService; + if (devHostSvcIf == NULL) { + return HDF_FAILURE; + } + if (isLoad && (deviceInfo->preload != DEVICE_PRELOAD_ENABLE)) { int ret = devHostSvcIf->AddDevice(devHostSvcIf, deviceInfo); if (ret == HDF_SUCCESS) { @@ -83,7 +86,7 @@ int32_t DevmgrServiceLoadLeftDriver(struct DevmgrService *devMgrSvc) if (deviceInfo->preload == DEVICE_PRELOAD_ENABLE_STEP2) { ret = DevmgrServiceActiveDevice(hostClnt, deviceInfo, true); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s load driver %s failed!", __func__, deviceInfo->moduleName); + HDF_LOGE("%s:failed to load driver %s", __func__, deviceInfo->moduleName); } } } @@ -91,7 +94,6 @@ int32_t DevmgrServiceLoadLeftDriver(struct DevmgrService *devMgrSvc) return HDF_SUCCESS; } - int DevmgrServiceLoadDevice(const char *svcName) { return DevmgrServiceFindAndActiveDevice(svcName, true); @@ -108,7 +110,7 @@ static struct DevHostServiceClnt *DevmgrServiceFindDeviceHost(struct IDevmgrServ struct DevHostServiceClnt *hostClnt = NULL; struct DevmgrService *dmService = (struct DevmgrService *)inst; if (dmService == NULL) { - HDF_LOGE("Find device host failed, dmService is null"); + HDF_LOGE("failed to find device host, dmService is null"); return NULL; } HdfSListIteratorInit(&it, &dmService->hosts); @@ -118,29 +120,49 @@ static struct DevHostServiceClnt *DevmgrServiceFindDeviceHost(struct IDevmgrServ return hostClnt; } } - HDF_LOGE("Find host failed, host id is %u", hostId); + HDF_LOGE("failed to find host, host id is %u", hostId); return NULL; } +static void DevmgrServiceUpdateStatus(struct DevHostServiceClnt *hostClnt, uint16_t deviceId, uint16_t status) +{ + struct HdfSListIterator it; + struct HdfDeviceInfo *deviceInfo = NULL; + + HdfSListIteratorInit(&it, hostClnt->deviceInfos); + while (HdfSListIteratorHasNext(&it)) { + deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&it); + if (deviceInfo->deviceId == deviceId) { + deviceInfo->status = status; + HDF_LOGD("%s host:%s %u device:%s %u status:%u", __func__, hostClnt->hostName, + hostClnt->hostId, deviceInfo->svcName, deviceId, deviceInfo->status); + return; + } + } + HDF_LOGE("%s: not find device %u in host %u", __func__, hostClnt->hostId, deviceId); + return; +} + static int DevmgrServiceAttachDevice( struct IDevmgrService *inst, const struct HdfDeviceInfo *deviceInfo, struct IHdfDeviceToken *token) { if (deviceInfo == NULL) { - HDF_LOGE("deviceInfo is null"); + HDF_LOGE("failed to attach device, deviceInfo is null"); return HDF_FAILURE; } struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, deviceInfo->hostId); if (hostClnt == NULL) { - HDF_LOGE("hostClnt is null"); + HDF_LOGE("failed to attach device, hostClnt is null"); return HDF_FAILURE; } struct DeviceTokenClnt *tokenClnt = DeviceTokenClntNewInstance(token); if (tokenClnt == NULL) { - HDF_LOGE("tokenClnt is null"); + HDF_LOGE("failed to attach device, tokenClnt is null"); return HDF_FAILURE; } tokenClnt->deviceInfo = deviceInfo; + DevmgrServiceUpdateStatus(hostClnt, deviceInfo->deviceId, HDF_SERVICE_USABLE); HdfSListAdd(&hostClnt->devices, &tokenClnt->node); return HDF_SUCCESS; } @@ -150,20 +172,21 @@ static int DevmgrServiceAttachDeviceHost( { struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, hostId); if (hostClnt == NULL) { - HDF_LOGE("Attach device host failed, hostClnt is null"); + HDF_LOGE("failed to attach device host, hostClnt is null"); return HDF_FAILURE; } if (hostService == NULL) { - HDF_LOGE("Attach device host failed, hostService is null"); + HDF_LOGE("failed to attach device host, hostService is null"); return HDF_FAILURE; } + + hostClnt->hostService = hostService; hostClnt->deviceInfos = HdfAttributeManagerGetDeviceList(hostClnt->hostId, hostClnt->hostName); if (hostClnt->deviceInfos == NULL) { - HDF_LOGE("Get device list failed"); - return HDF_FAILURE; + HDF_LOGW("failed to get device list "); + return HDF_SUCCESS; } hostClnt->devCount = HdfSListCount(hostClnt->deviceInfos); - hostClnt->hostService = hostService; return DevHostServiceClntInstallDriver(hostClnt); } @@ -181,7 +204,7 @@ static int DevmgrServiceStartDeviceHosts(struct DevmgrService *inst) } HdfSListInit(&hostList); if (!HdfAttributeManagerGetHostList(&hostList)) { - HDF_LOGW("%s get host list is null", __func__); + HDF_LOGW("%s: host list is null", __func__); return HDF_SUCCESS; } HdfSListIteratorInit(&it, &hostList); @@ -189,13 +212,13 @@ static int DevmgrServiceStartDeviceHosts(struct DevmgrService *inst) hostAttr = (struct HdfHostInfo *)HdfSListIteratorNext(&it); hostClnt = DevHostServiceClntNewInstance(hostAttr->hostId, hostAttr->hostName); if (hostClnt == NULL) { - HDF_LOGW("Create new device host client failed"); + HDF_LOGW("failed to create new device host client"); continue; } HdfSListAdd(&inst->hosts, &hostClnt->node); hostClnt->hostPid = installer->StartDeviceHost(hostAttr->hostId, hostAttr->hostName); if (hostClnt->hostPid == HDF_FAILURE) { - HDF_LOGW("Start device host failed, host id is %u", hostAttr->hostId); + HDF_LOGW("failed to start device host, host id is %u", hostAttr->hostId); HdfSListRemove(&inst->hosts, &hostClnt->node); DevHostServiceClntFreeInstance(hostClnt); } @@ -208,7 +231,7 @@ int DevmgrServiceStartService(struct IDevmgrService *inst) { struct DevmgrService *dmService = (struct DevmgrService *)inst; if (dmService == NULL) { - HDF_LOGE("Start device manager service failed, dmService is null"); + HDF_LOGE("failed to start device manager service, dmService is null"); return HDF_FAILURE; } return DevmgrServiceStartDeviceHosts(dmService); @@ -217,7 +240,7 @@ int DevmgrServiceStartService(struct IDevmgrService *inst) bool DevmgrServiceConstruct(struct DevmgrService *inst) { if (OsalMutexInit(&inst->devMgrMutex) != HDF_SUCCESS) { - HDF_LOGE("%s mutex init failed", __func__); + HDF_LOGE("%s:failed to mutex init ", __func__); return false; } struct IDevmgrService *devMgrSvcIf = (struct IDevmgrService *)inst; @@ -228,11 +251,12 @@ bool DevmgrServiceConstruct(struct DevmgrService *inst) devMgrSvcIf->AcquireWakeLock = DevmgrServiceAcquireWakeLock; devMgrSvcIf->ReleaseWakeLock = DevmgrServiceReleaseWakeLock; HdfSListInit(&inst->hosts); + return true; + } else { + return false; } - return true; } - struct HdfObject *DevmgrServiceCreate() { static bool isDevMgrServiceInit = false; diff --git a/core/manager/src/devsvc_manager.c b/core/manager/src/devsvc_manager.c index 7feac34c..1c7b765a 100644 --- a/core/manager/src/devsvc_manager.c +++ b/core/manager/src/devsvc_manager.c @@ -16,14 +16,14 @@ #define HDF_LOG_TAG devsvc_manager -struct DevSvcRecord *DevSvcManagerSearchService(struct IDevSvcManager *inst, uint32_t serviceKey) +static struct DevSvcRecord *DevSvcManagerSearchService(struct IDevSvcManager *inst, uint32_t serviceKey) { struct HdfSListIterator it; struct DevSvcRecord *record = NULL; struct DevSvcRecord *searchResult = NULL; struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst; if (devSvcManager == NULL) { - HDF_LOGE("Search service failed, devSvcManager is null"); + HDF_LOGE("failed to search service, devSvcManager is null"); return NULL; } @@ -44,13 +44,13 @@ int DevSvcManagerAddService(struct IDevSvcManager *inst, const char *svcName, st { struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst; if ((devSvcManager == NULL) || (service == NULL) || (svcName == NULL)) { - HDF_LOGE("Add service failed, input param is null"); + HDF_LOGE("failed to add service, input param is null"); return HDF_FAILURE; } struct DevSvcRecord *record = DevSvcRecordNewInstance(); if (record == NULL) { - HDF_LOGE("Add service failed, record is null"); + HDF_LOGE("failed to add service , record is null"); return HDF_FAILURE; } @@ -94,6 +94,7 @@ void DevSvcManagerRemoveService(struct IDevSvcManager *inst, const char *svcName HdfSListRemove(&devSvcManager->services, &serviceRecord->entry); OsalMutexUnlock(&devSvcManager->mutex); } + DevSvcRecordFreeInstance(serviceRecord); } struct HdfDeviceObject *DevSvcManagerGetObject(struct IDevSvcManager *inst, const char *svcName) @@ -134,7 +135,7 @@ bool DevSvcManagerConstruct(struct DevSvcManager *inst) devSvcMgrIf->GetObject = DevSvcManagerGetObject; HdfSListInit(&inst->services); if (OsalMutexInit(&inst->mutex) != HDF_SUCCESS) { - HDF_LOGE("Device service manager create mutex failed!"); + HDF_LOGE("failed to create device service manager mutex"); return false; } return true; @@ -171,4 +172,3 @@ struct IDevSvcManager *DevSvcManagerGetInstance() } return instance; } - diff --git a/core/manager/src/hdf_driver_installer.c b/core/manager/src/hdf_driver_installer.c index df91b52a..4071b2ee 100644 --- a/core/manager/src/hdf_driver_installer.c +++ b/core/manager/src/hdf_driver_installer.c @@ -23,7 +23,7 @@ static int DriverInstallerStartDeviceHost(uint32_t devHostId, const char *devHos } int ret = hostServiceIf->StartService(hostServiceIf); if (ret != HDF_SUCCESS) { - HDF_LOGE("Start host service failed, ret is: %d", ret); + HDF_LOGE("failed to start host service, ret: %d", ret); DevHostServiceFreeInstance(hostServiceIf); } return ret; diff --git a/core/manager/src/power_state_manager.c b/core/manager/src/power_state_manager.c index 99e02f50..29dcc7b1 100644 --- a/core/manager/src/power_state_manager.c +++ b/core/manager/src/power_state_manager.c @@ -62,7 +62,6 @@ static void PowerStateManagerReleaseWakeLock( static void PowerStateManagerConstruct(struct PowerStateManager *inst) { - // not support system acquire and release static struct IHdfSRefListener wakeLockRefListener = { .OnFirstAcquire = NULL, .OnLastRelease = NULL, diff --git a/core/manager/test/unittest/common/hdf_ioservice_test.cpp b/core/manager/test/unittest/common/hdf_ioservice_test.cpp index 75830ecf..9057d7be 100644 --- a/core/manager/test/unittest/common/hdf_ioservice_test.cpp +++ b/core/manager/test/unittest/common/hdf_ioservice_test.cpp @@ -72,12 +72,12 @@ int IoServiceTest::OnDevEventReceived(struct HdfDevEventlistener *listener, stru { OsalTimespec time; OsalGetTime(&time); - HDF_LOGE("%s received event[%d] from %s at %llu.%llu", (char *)listener->priv, eventCount++, (char *)service->priv, + HDF_LOGE("%s: received event[%d] from %s at %llu.%llu", (char *)listener->priv, eventCount++, (char *)service->priv, time.sec, time.usec); const char *string = HdfSbufReadString(data); if (string == nullptr) { - HDF_LOGE("fail to read string in event data"); + HDF_LOGE("failed to read string in event data"); return 0; } struct Eventlistener *l = CONTAINER_OF(listener, struct Eventlistener, listener); @@ -140,7 +140,7 @@ static int SendEvent(struct HdfIoService *serv, const char *eventData) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(IoServiceTest, HdfIoService001, TestSize.Level1) +HWTEST_F(IoServiceTest, HdfIoService001, TestSize.Level0) { struct HdfIoService *testServ = HdfIoServiceBind(testSvcName); ASSERT_NE(testServ, nullptr); @@ -149,11 +149,11 @@ HWTEST_F(IoServiceTest, HdfIoService001, TestSize.Level1) /* * * @tc.name: HdfIoService002 - * @tc.desc: service group linten test + * @tc.desc: service group listen test * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(IoServiceTest, HdfIoService002, TestSize.Level1) +HWTEST_F(IoServiceTest, HdfIoService002, TestSize.Level0) { struct HdfIoService *serv = HdfIoServiceBind(testSvcName); ASSERT_NE(serv, nullptr); @@ -203,7 +203,7 @@ HWTEST_F(IoServiceTest, HdfIoService002, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(IoServiceTest, HdfIoService003, TestSize.Level1) +HWTEST_F(IoServiceTest, HdfIoService003, TestSize.Level0) { struct HdfIoService *serv = HdfIoServiceBind(testSvcName); ASSERT_NE(serv, nullptr); @@ -258,7 +258,7 @@ HWTEST_F(IoServiceTest, HdfIoService003, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(IoServiceTest, HdfIoService004, TestSize.Level1) +HWTEST_F(IoServiceTest, HdfIoService004, TestSize.Level0) { struct HdfIoService *serv1 = HdfIoServiceBind(testSvcName); ASSERT_NE(serv1, nullptr); @@ -283,7 +283,7 @@ HWTEST_F(IoServiceTest, HdfIoService004, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(IoServiceTest, HdfIoService005, TestSize.Level1) +HWTEST_F(IoServiceTest, HdfIoService005, TestSize.Level0) { struct HdfIoService *serv = HdfIoServiceBind(testSvcName); ASSERT_NE(serv, nullptr); @@ -467,7 +467,7 @@ HWTEST_F(IoServiceTest, HdfIoService008, TestSize.Level0) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(IoServiceTest, HdfIoService009, TestSize.Level1) +HWTEST_F(IoServiceTest, HdfIoService009, TestSize.Level0) { struct HdfIoServiceGroup *group = HdfIoServiceGroupObtain(); ASSERT_NE(group, nullptr); @@ -504,7 +504,7 @@ HWTEST_F(IoServiceTest, HdfIoService009, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(IoServiceTest, HdfIoService010, TestSize.Level1) +HWTEST_F(IoServiceTest, HdfIoService010, TestSize.Level0) { struct HdfIoServiceGroup *group = HdfIoServiceGroupObtain(); ASSERT_NE(group, nullptr); @@ -544,7 +544,7 @@ HWTEST_F(IoServiceTest, HdfIoService010, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(IoServiceTest, HdfIoService011, TestSize.Level1) +HWTEST_F(IoServiceTest, HdfIoService011, TestSize.Level0) { struct HdfIoService *serv = HdfIoServiceBind(testSvcName); ASSERT_NE(serv, nullptr); @@ -573,7 +573,7 @@ HWTEST_F(IoServiceTest, HdfIoService011, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(IoServiceTest, HdfIoService012, TestSize.Level1) +HWTEST_F(IoServiceTest, HdfIoService012, TestSize.Level0) { struct HdfIoService *serv = HdfIoServiceBind(testSvcName); ASSERT_NE(serv, nullptr); diff --git a/core/manager/test/unittest/common/hdf_lite_manager_test.cpp b/core/manager/test/unittest/common/hdf_lite_manager_test.cpp index 8af642b1..623e4eb4 100644 --- a/core/manager/test/unittest/common/hdf_lite_manager_test.cpp +++ b/core/manager/test/unittest/common/hdf_lite_manager_test.cpp @@ -84,19 +84,19 @@ HWTEST_F(HdfManagerTest, HdfRegisterDevice001, TestSize.Level0) int32_t ret = HDF_FAILURE; struct HdfSBuf *data = NULL; struct HdfIoService *ioService = HdfIoServiceBind(SAMPLE_SERVICE); - ASSERT_TRUE(ioService != NULL); + EXPECT_TRUE(ioService != NULL); data = HdfSBufObtainDefaultSize(); - ASSERT_TRUE(data != NULL); + EXPECT_TRUE(data != NULL); EXPECT_TRUE(HdfSbufWriteString(data, "sample_driver")); EXPECT_TRUE(HdfSbufWriteString(data, "sample_service1")); - int64_t timeBefore = OsalGetSysTimeMs(); + uint64_t timeBefore = OsalGetSysTimeMs(); ret = ioService->dispatcher->Dispatch(&ioService->object, SAMPLE_DRIVER_REGISTER_DEVICE, data, NULL); EXPECT_TRUE(ret == HDF_SUCCESS); - int64_t timeAfter = OsalGetSysTimeMs(); + uint64_t timeAfter = OsalGetSysTimeMs(); EXPECT_TRUE((timeAfter - timeBefore) < 100); struct HdfIoService *ioService1 = HdfIoServiceBind("sample_service1"); - ASSERT_TRUE(ioService1 != NULL); + EXPECT_TRUE(ioService1 != NULL); HdfIoServiceRecycle(ioService1); ret = ioService->dispatcher->Dispatch(&ioService->object, SAMPLE_DRIVER_UNREGISTER_DEVICE, data, NULL); diff --git a/core/manager/test/unittest/common/hdf_sbuf_test.cpp b/core/manager/test/unittest/common/hdf_sbuf_test.cpp index 3f8fe8fe..4b5a9795 100644 --- a/core/manager/test/unittest/common/hdf_sbuf_test.cpp +++ b/core/manager/test/unittest/common/hdf_sbuf_test.cpp @@ -21,7 +21,7 @@ static const int DEFAULT_LOOP_COUNT = 500; static const int DEFAULT_BIG_LOOP_COUNT = 1000; static const int DATA_MOD = 26; -class SBufTest : public ::testing::Test { +class HdfSBufTest : public ::testing::Test { protected: void SetUp() override {} @@ -243,7 +243,7 @@ protected: * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestObtain001, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestObtain001, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtain(DEFAULT_SBUF_SIZE); ASSERT_NE(sBuf, nullptr); @@ -256,7 +256,7 @@ HWTEST_F(SBufTest, SbufTestObtain001, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestWriteUint64002, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestWriteUint64002, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -271,7 +271,7 @@ HWTEST_F(SBufTest, SbufTestWriteUint64002, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestWriteUint64Loop003, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestWriteUint64Loop003, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -288,7 +288,7 @@ HWTEST_F(SBufTest, SbufTestWriteUint64Loop003, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestReadUint64Loop004, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestReadUint64Loop004, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -297,7 +297,7 @@ HWTEST_F(SBufTest, SbufTestReadUint64Loop004, TestSize.Level1) auto ret = HdfSbufWriteInt64(sBuf, INT64_MAX); ASSERT_EQ(ret, true); } - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); uint64_t val = 0; for (int j = 0; j < loop; ++j) { @@ -318,7 +318,7 @@ HWTEST_F(SBufTest, SbufTestReadUint64Loop004, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestInt8005, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestInt8005, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -331,7 +331,7 @@ HWTEST_F(SBufTest, SbufTestInt8005, TestSize.Level1) size_t dataSize = HdfSbufGetDataSize(sBuf); ASSERT_EQ(dataSize, loop * sizeof(uint32_t)); - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); int8_t val = 0; @@ -351,7 +351,7 @@ HWTEST_F(SBufTest, SbufTestInt8005, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestInt16006, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestInt16006, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -364,7 +364,7 @@ HWTEST_F(SBufTest, SbufTestInt16006, TestSize.Level1) size_t dataSize = HdfSbufGetDataSize(sBuf); ASSERT_EQ(dataSize, loop * sizeof(uint32_t)); - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); int16_t val = 0; @@ -384,7 +384,7 @@ HWTEST_F(SBufTest, SbufTestInt16006, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestInt32007, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestInt32007, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -397,7 +397,7 @@ HWTEST_F(SBufTest, SbufTestInt32007, TestSize.Level1) size_t dataSize = HdfSbufGetDataSize(sBuf); ASSERT_EQ(dataSize, loop * sizeof(uint32_t)); - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); int32_t val = 0; @@ -417,7 +417,7 @@ HWTEST_F(SBufTest, SbufTestInt32007, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestInt64008, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestInt64008, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -430,7 +430,7 @@ HWTEST_F(SBufTest, SbufTestInt64008, TestSize.Level1) size_t dataSize = HdfSbufGetDataSize(sBuf); ASSERT_EQ(dataSize, loop * sizeof(uint64_t)); - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); int64_t val = 0; @@ -450,7 +450,7 @@ HWTEST_F(SBufTest, SbufTestInt64008, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestUInt32009, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestUInt32009, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -463,7 +463,7 @@ HWTEST_F(SBufTest, SbufTestUInt32009, TestSize.Level1) size_t dataSize = HdfSbufGetDataSize(sBuf); ASSERT_EQ(dataSize, loop * sizeof(uint32_t)); - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); uint32_t val = 0; @@ -483,7 +483,7 @@ HWTEST_F(SBufTest, SbufTestUInt32009, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestUInt16010, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestUInt16010, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -496,7 +496,7 @@ HWTEST_F(SBufTest, SbufTestUInt16010, TestSize.Level1) size_t dataSize = HdfSbufGetDataSize(sBuf); ASSERT_EQ(dataSize, loop * sizeof(uint32_t)); - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); uint16_t val = 0; @@ -516,7 +516,7 @@ HWTEST_F(SBufTest, SbufTestUInt16010, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestUInt8011, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestUInt8011, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -529,7 +529,7 @@ HWTEST_F(SBufTest, SbufTestUInt8011, TestSize.Level1) size_t dataSize = HdfSbufGetDataSize(sBuf); ASSERT_EQ(dataSize, loop * sizeof(uint32_t)); - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); uint8_t val = 0; @@ -549,7 +549,7 @@ HWTEST_F(SBufTest, SbufTestUInt8011, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestString012, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestString012, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -561,12 +561,11 @@ HWTEST_F(SBufTest, SbufTestString012, TestSize.Level1) ASSERT_EQ(ret, true); } - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); for (int j = 0; j < loop; ++j) { const char *readStr = HdfSbufReadString(readBuf); - ASSERT_NE(readStr, nullptr); ASSERT_EQ(std::string(readStr), str); } HdfSBufRecycle(readBuf); @@ -579,7 +578,7 @@ HWTEST_F(SBufTest, SbufTestString012, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestNullString013, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestNullString013, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -589,7 +588,7 @@ HWTEST_F(SBufTest, SbufTestNullString013, TestSize.Level1) ASSERT_EQ(true, ret); size_t dataSize = HdfSbufGetDataSize(sBuf); ASSERT_NE((size_t)0, dataSize); - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); auto val = HdfSbufReadString(readBuf); ASSERT_EQ(nullptr, val); @@ -607,7 +606,7 @@ HWTEST_F(SBufTest, SbufTestNullString013, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestBuffer014, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestBuffer014, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -619,7 +618,7 @@ HWTEST_F(SBufTest, SbufTestBuffer014, TestSize.Level1) ASSERT_EQ(ret, true); } - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); for (int j = 0; j < loop; ++j) { @@ -640,7 +639,7 @@ HWTEST_F(SBufTest, SbufTestBuffer014, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestNullBuffer015, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestNullBuffer015, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -650,7 +649,7 @@ HWTEST_F(SBufTest, SbufTestNullBuffer015, TestSize.Level1) ASSERT_EQ(true, ret); size_t dataSize = HdfSbufGetDataSize(sBuf); ASSERT_NE((size_t)0, dataSize); - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); const uint8_t *buffVal = nullptr; uint32_t buffLen = 0; @@ -673,7 +672,7 @@ HWTEST_F(SBufTest, SbufTestNullBuffer015, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestRandomDataSeq016, TestSize.Level0) +HWTEST_F(HdfSBufTest, SbufTestRandomDataSeq016, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -683,7 +682,7 @@ HWTEST_F(SBufTest, SbufTestRandomDataSeq016, TestSize.Level0) bool ret = PushDataSequence(sBuf); ASSERT_EQ(true, ret); - HdfSBuf *readBuf = HdfSBufBind((uintptr_t)sBuf->data, sBuf->writePos); + HdfSBuf *readBuf = HdfSBufBind((uintptr_t)HdfSbufGetData(sBuf), HdfSbufGetDataSize(sBuf)); ASSERT_NE(readBuf, nullptr); ret = PullDataSequence(readBuf); @@ -698,7 +697,7 @@ HWTEST_F(SBufTest, SbufTestRandomDataSeq016, TestSize.Level0) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestRandomRWDataSeq017, TestSize.Level0) +HWTEST_F(HdfSBufTest, SbufTestRandomRWDataSeq017, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -731,7 +730,7 @@ HWTEST_F(SBufTest, SbufTestRandomRWDataSeq017, TestSize.Level0) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestSbufMove018, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestSbufMove018, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); @@ -768,7 +767,7 @@ HWTEST_F(SBufTest, SbufTestSbufMove018, TestSize.Level1) * @tc.type: FUNC * @tc.require: AR000F869B */ -HWTEST_F(SBufTest, SbufTestSbufMoveHalf019, TestSize.Level1) +HWTEST_F(HdfSBufTest, SbufTestSbufMoveHalf019, TestSize.Level1) { HdfSBuf *sBuf = HdfSBufObtainDefaultSize(); ASSERT_NE(sBuf, nullptr); diff --git a/core/sec/include/hdf_sec.h b/core/sec/include/hdf_sec.h new file mode 100644 index 00000000..90e3fd73 --- /dev/null +++ b/core/sec/include/hdf_sec.h @@ -0,0 +1,56 @@ +/* + * 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_SEC_H +#define HDF_SEC_H + +#if defined(__KERNEL__) +#include +#include +#else +#include +#include +#include +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#define DEVICE_HDF_SECURE_NAME "hdf_secure" +#define HDF_SECURE_MAGIC 'S' + +/* event commands */ +#define HDF_SECURE_SET_INFO _IO(HDF_SECURE_MAGIC, 0x1) +#define HDF_SECURE_SET_CURRENT_ID _IO(HDF_SECURE_MAGIC, 0x2) +#define HDF_SECURE_DELETE_INFO _IO(HDF_SECURE_MAGIC, 0x3) + +#define HDF_DECLARE_BITMAP(name, bits) \ + uint64_t name[HDF_BITS_TO_LONGS(bits)] +#define HDF_BITS_TO_LONGS(nr) HDF_DIV_ROUND_UP(nr, HDF_BITS_PER_BYTE * sizeof(uint64_t)) +#define HDF_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) +#define HDF_BITS_PER_BYTE 8 + +#define SECMAP_MAX_SIZE 64 +#define ID_MAX_SIZE 65 + +struct SecInfo { + char secId[ID_MAX_SIZE]; + HDF_DECLARE_BITMAP(secMap, SECMAP_MAX_SIZE); +}; +uint32_t hdf_permission_check(uint8_t type); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* HDF_SEC_H */ diff --git a/core/shared/include/hdf_device_info.h b/core/shared/include/hdf_device_info.h old mode 100644 new mode 100755 index a5fa7812..b77ec148 --- a/core/shared/include/hdf_device_info.h +++ b/core/shared/include/hdf_device_info.h @@ -12,9 +12,24 @@ #include "hdf_device_desc.h" #include "hdf_slist.h" +#define USB_PNP_INFO_MAX_INTERFACES 32 +#define USB_PNP_DEBUG_STRING "" + +enum { + HDF_SERVICE_UNUSABLE, + HDF_SERVICE_USABLE, +}; + +enum { + HDF_DEV_LOCAL_SERVICE, + HDF_DEV_REMOTE_SERVICE, +}; + struct HdfDeviceInfo { struct HdfSListNode node; bool isDynamic; + uint16_t status; + uint16_t deviceType; uint16_t hostId; uint16_t deviceId; uint16_t policy; @@ -24,6 +39,75 @@ struct HdfDeviceInfo { const char *moduleName; const char *svcName; const char *deviceMatchAttr; + const void *private; +}; + +enum UsbPnpNotifyServiceCmd { + USB_PNP_NOTIFY_ADD_INTERFACE, + USB_PNP_NOTIFY_REMOVE_INTERFACE, + USB_PNP_NOTIFY_REPORT_INTERFACE, +}; + +enum UsbPnpNotifyRemoveType { + USB_PNP_NOTIFY_REMOVE_BUS_DEV_NUM, + USB_PNP_NOTIFY_REMOVE_INTERFACE_NUM, +}; + +enum { + USB_PNP_NOTIFY_MATCH_VENDOR = 0x0001, + USB_PNP_NOTIFY_MATCH_PRODUCT = 0x0002, + USB_PNP_NOTIFY_MATCH_DEV_LOW = 0x0004, + USB_PNP_NOTIFY_MATCH_DEV_HIGH = 0x0008, + USB_PNP_NOTIFY_MATCH_DEV_CLASS = 0x0010, + USB_PNP_NOTIFY_MATCH_DEV_SUBCLASS = 0x0020, + USB_PNP_NOTIFY_MATCH_DEV_PROTOCOL = 0x0040, + USB_PNP_NOTIFY_MATCH_INT_CLASS = 0x0080, + USB_PNP_NOTIFY_MATCH_INT_SUBCLASS = 0x0100, + USB_PNP_NOTIFY_MATCH_INT_PROTOCOL = 0x0200, + USB_PNP_NOTIFY_MATCH_INT_NUMBER = 0x0400, +}; + +struct UsbPnpNotifyServiceInfo { + int32_t length; + + int32_t devNum; + int32_t busNum; + + int32_t interfaceLength; + uint8_t interfaceNumber[USB_PNP_INFO_MAX_INTERFACES]; +} __attribute__ ((packed)); + +struct UsbPnpNotifyInterfaceInfo { + uint8_t interfaceClass; + uint8_t interfaceSubClass; + uint8_t interfaceProtocol; + + uint8_t interfaceNumber; +}; + +struct UsbPnpNotifyDeviceInfo { + uint16_t vendorId; + uint16_t productId; + + uint16_t bcdDeviceLow; + uint16_t bcdDeviceHigh; + + uint8_t deviceClass; + uint8_t deviceSubClass; + uint8_t deviceProtocol; +}; + +struct UsbPnpNotifyMatchInfoTable { + uint32_t usbDevAddr; + int32_t devNum; + int32_t busNum; + + struct UsbPnpNotifyDeviceInfo deviceInfo; + + uint8_t removeType; + uint8_t numInfos; + + struct UsbPnpNotifyInterfaceInfo interfaceInfo[USB_PNP_INFO_MAX_INTERFACES]; }; struct HdfDeviceInfo *HdfDeviceInfoNewInstance(void); diff --git a/core/shared/include/hdf_io_service.h b/core/shared/include/hdf_io_service.h index 6887fa61..2fcdf3d8 100644 --- a/core/shared/include/hdf_io_service.h +++ b/core/shared/include/hdf_io_service.h @@ -20,8 +20,8 @@ extern "C" { #define DEV_MGR_NODE "dev_mgr" #define MAX_MODE_SIZE 0777 #define DEV_NODE_PATH_MODE 0755 -#define HDF_WRITE_READ _IOWR('b', 1, struct HdfSBuf) -#define HDF_READ_DEV_EVENT _IOR('b', 2, struct HdfSBuf) +#define HDF_WRITE_READ _IOWR('b', 1, struct HdfSBuf*) +#define HDF_READ_DEV_EVENT _IOR('b', 2, struct HdfSBuf*) #define HDF_LISTEN_EVENT_START _IO('b', 3) #define HDF_LISTEN_EVENT_STOP _IO('b', 4) #define HDF_LISTEN_EVENT_WAKEUP _IO('b', 5) diff --git a/core/shared/src/hdf_device_info.c b/core/shared/src/hdf_device_info.c old mode 100644 new mode 100755 index d30bb3fb..29653af9 --- a/core/shared/src/hdf_device_info.c +++ b/core/shared/src/hdf_device_info.c @@ -19,6 +19,8 @@ void HdfDeviceInfoConstruct(struct HdfDeviceInfo *deviceInfo) } deviceInfo->isDynamic = false; deviceInfo->hostId = 0; + deviceInfo->status = HDF_SERVICE_UNUSABLE; + deviceInfo->deviceType = HDF_DEV_LOCAL_SERVICE; deviceInfo->deviceId = 0; deviceInfo->policy = SERVICE_POLICY_INVALID; deviceInfo->priority = 0; @@ -27,6 +29,7 @@ void HdfDeviceInfoConstruct(struct HdfDeviceInfo *deviceInfo) deviceInfo->svcName = NULL; deviceInfo->moduleName = NULL; deviceInfo->deviceMatchAttr = NULL; + deviceInfo->private = NULL; } struct HdfDeviceInfo *HdfDeviceInfoNewInstance() diff --git a/core/shared/src/hdf_service_record.c b/core/shared/src/hdf_service_record.c index 269fcd7e..ebc9c389 100644 --- a/core/shared/src/hdf_service_record.c +++ b/core/shared/src/hdf_service_record.c @@ -27,4 +27,3 @@ void DevSvcRecordDelete(struct HdfSListNode *listEntry) OsalMemFree(listEntry); } } - diff --git a/include/config/device_resource_if.h b/include/config/device_resource_if.h index 4bc009ff..4775bd84 100644 --- a/include/config/device_resource_if.h +++ b/include/config/device_resource_if.h @@ -10,12 +10,12 @@ * @addtogroup DriverConfig * @{ * - * @brief Defines an API for HDF driver developers to read driver configuration information. + * @brief Defines APIs for HDF driver developers to read driver configuration information. * * During version compilation of the device resource source file defined by developers, the compilation tool * (for example, the compilation tool of the HCS file is hc-gen) generates bytecodes. When the HDF starts, * it transfers the bytecode memory to the DriverConfig module. The DriverConfig module converts - * the bytecodes into a configuration tree and provides an API for developers to query the tree. + * the bytecodes into a configuration tree and provides APIs for developers to query the tree. * * @since 1.0 * @version 1.0 @@ -24,7 +24,7 @@ /** * @file device_resource_if.h * - * @brief Declares the API for querying the configuration tree. + * @brief Declares the APIs for querying the configuration tree. * * @since 1.0 * @version 1.0 @@ -142,7 +142,7 @@ struct DeviceResourceIface { int32_t (*GetUint8ArrayElem)(const struct DeviceResourceNode *node, const char *attrName, uint32_t index, uint8_t *value, uint8_t def); /** - * @brief Obtains the values of a Uint8 array attribute of a configuration tree node. + * @brief Obtains the value of a Uint8 array attribute of a configuration tree node. * * @param node Indicates the pointer to the configuration tree node. * @param attrName Indicates the pointer to the name of the array attribute. @@ -443,5 +443,5 @@ struct DeviceResourceIface *DeviceResourceGetIfaceInstance(DeviceResourceType ty #endif #endif /* __cplusplus */ -#endif // DEVICE_RESOURCE_IF_H +#endif /* DEVICE_RESOURCE_IF_H */ /** @} */ diff --git a/include/core/hdf_device_desc.h b/include/core/hdf_device_desc.h index 9c55e21c..367949cb 100644 --- a/include/core/hdf_device_desc.h +++ b/include/core/hdf_device_desc.h @@ -10,7 +10,7 @@ * @addtogroup Core * @{ * - * @brief Provides OpenHarmony Driver Foundation (HDF) APIs. + * @brief Provides Hardware Driver Foundation (HDF) APIs. * * The HDF implements driver framework capabilities such as driver loading, service management, * and driver message model. You can develop drivers based on the HDF. @@ -177,21 +177,6 @@ struct SubscriberCallback { int32_t (*OnServiceConnected)(struct HdfDeviceObject *deviceObject, const struct HdfObject *service); }; -/** - * @brief Defines the power management functions provided by the HDF for the driver. - * - * To use the power management mechanism provided by the HDF, implement operations of IPowerEventListener and - * invoke {@linkHdfDeviceRegisterPowerListener} to register the operations with the HDF. - * - * @since 1.0 - */ -struct IPowerEventListener { - /** Wakes up the driver device. The driver developer implements the operation. */ - void (*Resume)(struct HdfDeviceObject *deviceObject); - /** Hibernates the driver device. The driver developer implements the operation. */ - void (*Suspend)(struct HdfDeviceObject *deviceObject); -}; - /** * @brief Defines the entry structure of the driver in the HDF. * diff --git a/include/core/hdf_object.h b/include/core/hdf_object.h index d73da125..adfbbe72 100644 --- a/include/core/hdf_object.h +++ b/include/core/hdf_object.h @@ -10,7 +10,7 @@ * @addtogroup Core * @{ * - * @brief Provides OpenHarmony Driver Foundation (HDF) APIs. + * @brief Provides Hardware Driver Foundation (HDF) APIs. * * The HDF implements driver framework capabilities such as driver loading, service management, * and driver message model. You can develop drivers based on the HDF. diff --git a/include/core/hdf_pm.h b/include/core/hdf_pm.h new file mode 100644 index 00000000..fbf6e3af --- /dev/null +++ b/include/core/hdf_pm.h @@ -0,0 +1,47 @@ +/* + * 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_POWER_MANAGEMENT_H +#define HDF_POWER_MANAGEMENT_H + +#include "hdf_device_desc.h" +#include "osal_sysevent.h" + +enum PowerManagementMode { + HDF_POWER_SYS_CTRL, + HDF_POWER_DYNAMIC_CTRL, + HDF_POWER_MODE_MAX, +}; + +/** + * @brief Defines the power management functions provided by the HDF for the driver. + * + * To use the power management mechanism provided by the HDF, implement operations of IPowerEventListener and + * invoke {@linkHdfDeviceRegisterPowerListener} to register the operations with the HDF. + * + * @since 1.0 + */ +struct IPowerEventListener { + int (*DozeResume)(struct HdfDeviceObject *deviceObject); + int (*DozeSuspend)(struct HdfDeviceObject *deviceObject); + /** Wakes up the driver device. The driver developer implements the operation. */ + int (*Resume)(struct HdfDeviceObject *deviceObject); + /** Hibernates the driver device. The driver developer implements the operation. */ + int (*Suspend)(struct HdfDeviceObject *deviceObject); +}; + +static inline bool HdfPmIsWakeEvent(int sysEvent) +{ + return sysEvent >= KEVENT_POWER_RESUME && sysEvent <= KEVENT_POWER_DISPLAY_ON; +} + +int HdfPmRegisterPowerListener(struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener); +void HdfPmUnregisterPowerListener(struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener); +void HdfPmAcquireDevice(struct HdfDeviceObject *deviceObject); +void HdfPmReleaseDevice(struct HdfDeviceObject *deviceObject); +void HdfPmSetMode(struct HdfDeviceObject *deviceObject, uint32_t mode); +#endif /* HDF_POWER_MANAGEMENT_H */ diff --git a/include/osal/osal_firmware.h b/include/osal/osal_firmware.h index 6053643a..2c82c5f4 100644 --- a/include/osal/osal_firmware.h +++ b/include/osal/osal_firmware.h @@ -87,6 +87,23 @@ struct OsalFwBlock { */ int32_t OsalRequestFirmware(struct OsalFirmware *fw, const char *fwName, void *device); +/** + * @brief Sets the offset for reading a firmware file to implement random access to the firmware file. + * + * @param fw Indicates the pointer to the firmware file {@link OsalFirmware}. + * @param offset Indicates the offset where the firmware content is to read. + * + * @return Returns a value listed below: \n + * HDF_STATUS | Description + * ----------------------| ----------------------- + * HDF_SUCCESS | The operation is successful. + * HDF_ERR_INVALID_PARAM | Invalid parameter. + * + * @since 1.0 + * @version 1.0 + */ +int32_t OsalSeekFirmware(struct OsalFirmware *fw, uint32_t offset); + /** * @brief Reads a firmware file. * @@ -103,7 +120,7 @@ int32_t OsalRequestFirmware(struct OsalFirmware *fw, const char *fwName, void *d * @since 1.0 * @version 1.0 */ -int32_t OsalSeekFirmware(struct OsalFirmware *fw, uint32_t offset); +int32_t OsalReadFirmware(struct OsalFirmware *fw, struct OsalFwBlock *block); /** * @brief Releases a firmware file. @@ -122,15 +139,6 @@ int32_t OsalSeekFirmware(struct OsalFirmware *fw, uint32_t offset); * @since 1.0 * @version 1.0 */ -int32_t OsalReadFirmware(struct OsalFirmware *fw, struct OsalFwBlock *block); - -/** - * Release firmware resource - * - * @param : fw Firmware parameter, see detail in OsalFirmware - * block Firmware data block, see detail in hdf_FWBlock - * @return : true or false - */ int32_t OsalReleaseFirmware(struct OsalFirmware *fw); #ifdef __cplusplus diff --git a/include/osal/osal_sem.h b/include/osal/osal_sem.h index 80409757..eb36b185 100644 --- a/include/osal/osal_sem.h +++ b/include/osal/osal_sem.h @@ -37,6 +37,8 @@ extern "C" { #endif /* __cplusplus */ +#define OSAL_WAIT_FOREVER 0xFFFFFFFF + /** * @brief Describes a semaphore. */ diff --git a/include/utils/hdf_dlist.h b/include/utils/hdf_dlist.h index cc243f40..369cb089 100644 --- a/include/utils/hdf_dlist.h +++ b/include/utils/hdf_dlist.h @@ -194,6 +194,12 @@ static inline void DListMerge(struct DListHead *list, struct DListHead *head) &(pos)->member != (head); \ (pos) = CONTAINER_OF((pos)->member.next, type, member)) + +#define DLIST_FOR_EACH_ENTRY_REVERSE(pos, head, type, member) \ + for ((pos) = CONTAINER_OF((head)->prev, type, member); \ + &(pos)->member != (head); \ + (pos) = CONTAINER_OF((pos)->member.prev, type, member)) + /** * @brief Traverses all nodes in a doubly linked list. * This function is used to delete the nodes pointed to by pos during traversal. diff --git a/utils/include/hdf_map.h b/utils/include/hdf_map.h new file mode 100644 index 00000000..df6c690c --- /dev/null +++ b/utils/include/hdf_map.h @@ -0,0 +1,40 @@ +/* + * 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_MAP_H +#define HDF_MAP_H + +#include "hdf_base.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct MapNode; + +typedef struct { + struct MapNode **nodes; /**< Map node bucket */ + uint32_t nodeSize; /**< Map node count */ + uint32_t bucketSize; /**< Map node bucket size */ +} Map; + +void MapInit(Map *map); + +void MapDelete(Map *map); + +int32_t MapSet(Map *map, const char *key, const void *value, uint32_t valueSize); + +void *MapGet(const Map *map, const char *key); + +int32_t MapErase(Map *map, const char *key); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* HDF_MAP_H */ diff --git a/utils/include/hdf_message_looper.h b/utils/include/hdf_message_looper.h new file mode 100644 index 00000000..d11d79a9 --- /dev/null +++ b/utils/include/hdf_message_looper.h @@ -0,0 +1,32 @@ +/* + * 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_MESSAGE_LOOPER_H +#define HDF_MESSAGE_LOOPER_H + +#include "osal_msg_queue.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define MESSAGE_STOP_LOOP (-1) + +struct HdfMessageLooper { + struct HdfMessageQueue messageQueue; + void (*Start)(struct HdfMessageLooper *); + void (*Stop)(struct HdfMessageLooper *); +}; + +void HdfMessageLooperConstruct(struct HdfMessageLooper *looper); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* HDF_MESSAGE_LOOPER_H */ diff --git a/utils/include/hdf_message_task.h b/utils/include/hdf_message_task.h new file mode 100644 index 00000000..9719084f --- /dev/null +++ b/utils/include/hdf_message_task.h @@ -0,0 +1,41 @@ +/* + * 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_MESSAGE_TASK_H +#define HDF_MESSAGE_TASK_H + +#include "hdf_message_looper.h" +#include "osal_msg_queue.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct HdfMessageTask; + +struct IHdfMessageHandler { + int32_t (*Dispatch)(struct HdfMessageTask *task, struct HdfMessage *msg); +}; + +struct HdfMessageTask { + int32_t (*SendMessage)(struct HdfMessageTask *task, struct HdfMessage *msg, bool sync); + void (*RemoveMessage)(struct HdfMessageTask *task, struct HdfMessage *msg); + void (*SendMessageLater)(struct HdfMessageTask *task, struct HdfMessage *msg, long delay); + void (*DispatchMessage)(struct HdfMessageTask *task, struct HdfMessage *msg); + struct HdfMessageQueue *messageQueue; + struct IHdfMessageHandler *messageHandler; +}; + +void HdfMessageTaskConstruct(struct HdfMessageTask *inst, + struct HdfMessageLooper *looper, struct IHdfMessageHandler *handler); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* HDF_MESSAGE_TASK_H */ diff --git a/utils/include/hdf_slist.h b/utils/include/hdf_slist.h index 94ec646e..f6b47a52 100644 --- a/utils/include/hdf_slist.h +++ b/utils/include/hdf_slist.h @@ -31,14 +31,14 @@ struct HdfSListIterator { typedef void (*HdfSListDeleter)(struct HdfSListNode *); -typedef bool (*HdfSListSearchCompare)(struct HdfSListNode *, uint32_t); +typedef bool (*HdfSListSearchComparer)(struct HdfSListNode *, uint32_t); -typedef bool (*HdfSListAddCompare)(struct HdfSListNode *, struct HdfSListNode *); +typedef bool (*HdfSListAddComparer)(struct HdfSListNode *, struct HdfSListNode *); /* * @brief Init the list * - * @param[in] list :the operation list. + * @param[in] list the operation list. * * @return None */ @@ -48,13 +48,13 @@ void HdfSListInit(struct HdfSList *list); * @brief search to see whether specific element is attach into the list. * * @param[in] list the operation list. - * @param[in] searchKey -search key of list node. - * @param[in] comparer -comparer of list node. + * @param[in] searchKey search key of list node. + * @param[in] comparer comparer of list node. * * @return struct HdfSListNode of search result * -# NULL if not found. */ -struct HdfSListNode *HdfSListSearch(struct HdfSList *list, uint32_t searchKey, HdfSListSearchCompare compare); +struct HdfSListNode *HdfSListSearch(struct HdfSList *list, uint32_t searchKey, HdfSListSearchComparer comparer); /* * @brief tests if list is empty @@ -77,8 +77,8 @@ struct HdfSListNode *HdfSListGetLast(struct HdfSList *list); /* * @brief add item to the head of the list * - * @param[in] list :the operation list. - * @param[in] p_node :the new element to add. + * @param[in] list the operation list. + * @param[in] link the new element to add. * * @return None */ @@ -88,7 +88,7 @@ void HdfSListAdd(struct HdfSList *list, struct HdfSListNode *link); * @brief add item to list as last element * * @param[in] list the operation list. - * @param[in] p_node :the new element to add. + * @param[in] link the new element to add. * * @return None */ @@ -98,22 +98,19 @@ void HdfSListAddTail(struct HdfSList *list, struct HdfSListNode *link); * @brief add item to list as ordered * * @param[in] list the operation list. - * @param[in] p_node :the new element to add. - * @param[in] comparer :compared. + * @param[in] link the new element to add. + * @param[in] comparer comparer of list node. * * @return bool result of queue status. */ -bool HdfSListAddOrder(struct HdfSList *list, struct HdfSListNode *link, HdfSListAddCompare compare); +bool HdfSListAddOrder(struct HdfSList *list, struct HdfSListNode *link, HdfSListAddComparer comparer); /* * @brief remove item from list * - * @param[in] list :the operation list. - * @param[in] p_node :the element to remove. + * @param[in] list the operation list. + * @param[in] link the element to remove. * - * @return the result of remove node. - * -# HDF_SUCCESS link has been successfully removed. - * -# HDF_FAILURE link was not found in the list. */ void HdfSListRemove(struct HdfSList *list, struct HdfSListNode *link); @@ -121,7 +118,7 @@ void HdfSListRemove(struct HdfSList *list, struct HdfSListNode *link); * @brief flush the list and free memory * * @param[in] list the operation list. - * @param[in] deleter :the func of free memory. + * @param[in] deleter the function of free memory. * * @return None */ @@ -130,7 +127,7 @@ void HdfSListFlush(struct HdfSList *list, HdfSListDeleter deleter); /* * @brief calculate the element count in the list. * - * @param[in] list :the list to count. + * @param[in] list the list to count. * * @return the count of list. */ @@ -146,9 +143,9 @@ int HdfSListCount(struct HdfSList *list); struct HdfSListNode *HdfSListPeek(struct HdfSList *list); /* - * @brief get next element of p_link; + * @brief get next element of link; * - * @param[in] p_link: the operation link. + * @param[in] link the operation link. * * @return the next element of the link pass in */ @@ -203,7 +200,8 @@ void HdfSListIteratorRemove(struct HdfSListIterator *iterator); /* * @brief insert new node before the node that iterator point to.and hold current iterator. * - * @param[in] list the operation list. + * @param[in] iterator the point of iterator. + * @param[in] link the point of operation list. * * @return None */ diff --git a/utils/include/hdf_sref.h b/utils/include/hdf_sref.h index bfc4b6c5..04c1a367 100644 --- a/utils/include/hdf_sref.h +++ b/utils/include/hdf_sref.h @@ -27,10 +27,12 @@ struct HdfSRef { struct IHdfSRefListener *listener; void (*Acquire)(struct HdfSRef *); void (*Release)(struct HdfSRef *); + int (*Count)(const struct HdfSRef *); }; void HdfSRefAcquire(struct HdfSRef *sref); void HdfSRefRelease(struct HdfSRef *sref); +int HdfSRefCount(const struct HdfSRef *sref); void HdfSRefConstruct(struct HdfSRef *sref, struct IHdfSRefListener *listener); #ifdef __cplusplus diff --git a/utils/include/hdf_thread_ex.h b/utils/include/hdf_thread_ex.h new file mode 100644 index 00000000..fad57898 --- /dev/null +++ b/utils/include/hdf_thread_ex.h @@ -0,0 +1,38 @@ +/* + * 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_THREAD_H +#define HDF_THREAD_H + +#include +#include "osal_thread.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct HdfThread { + struct OsalThread adapter; + bool status; + void (*ThreadEntry)(void *); + bool (*IsRunning)(); + void (*Start)(struct HdfThread *thread); + void (*Stop)(struct HdfThread *thread); +}; + +void HdfThreadConstruct(struct HdfThread *thread); +void HdfThreadDestruct(struct HdfThread *thread); +struct HdfThread *HdfThreadNewInstance(void); +void HdfThreadFreeInstance(struct HdfThread *instance); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* HDF_THREAD_H */ + diff --git a/utils/include/osal_cdev.h b/utils/include/osal_cdev.h new file mode 100644 index 00000000..b6895493 --- /dev/null +++ b/utils/include/osal_cdev.h @@ -0,0 +1,50 @@ +/* + * 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 OSAL_CDEV_H +#define OSAL_CDEV_H + +#include "osal_cdev_adapter.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef __user +#define __user +#endif + +struct OsalCdev; +struct file; + +struct OsalCdevOps { + int64_t (*seek)(struct file* filep, int64_t offset, int whence); + ssize_t (*read)(struct file* filep, char __user* buffer, size_t buflen, int64_t* offset); + ssize_t (*write)(struct file* filep, const char __user* buffer, size_t buflen, int64_t* offset); + unsigned int (*poll)(struct file* filep, poll_table* pollTable); + long (*ioctl)(struct file* filep, unsigned int cmd, unsigned long arg); + int (*open)(struct OsalCdev* cdev, struct file* filep); + int (*release)(struct OsalCdev* cdev, struct file* filep); +}; + +struct OsalCdev* OsalAllocCdev(const struct OsalCdevOps* fops); +int OsalRegisterCdev(struct OsalCdev* cdev, const char *name, unsigned int mode, void *priv); +void OsalUnregisterCdev(struct OsalCdev* cdev); +void OsalFreeCdev(struct OsalCdev* cdev); + +void* OsalGetCdevPriv(struct OsalCdev* cdev); + +void OsalSetFilePriv(struct file* filep, void *priv); +void* OsalGetFilePriv(struct file* filep); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OSAL_CDEV_H */ +/** @} */ diff --git a/utils/include/osal_message.h b/utils/include/osal_message.h new file mode 100644 index 00000000..f06959f4 --- /dev/null +++ b/utils/include/osal_message.h @@ -0,0 +1,34 @@ +/* + * 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 OSAL_MESSAGE_H +#define OSAL_MESSAGE_H + +#include "hdf_slist.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct HdfMessage { + struct HdfSListNode entry; + struct HdfMessageTask *target; + int16_t messageId; + uint64_t timeStamp; + void *data[1]; +}; + +struct HdfMessage *HdfMessageObtain(size_t extendSize); +void HdfMessageRecycle(struct HdfMessage *message); +void HdfMessageDelete(struct HdfSListNode *listEntry); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OSAL_MESSAGE_H */ diff --git a/utils/include/osal_msg_queue.h b/utils/include/osal_msg_queue.h new file mode 100644 index 00000000..38ed3141 --- /dev/null +++ b/utils/include/osal_msg_queue.h @@ -0,0 +1,38 @@ +/* + * 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 OSAL_MSG_QUEUE_H +#define OSAL_MSG_QUEUE_H + +#include "hdf_slist.h" +#include "osal_message.h" +#include "osal_mutex.h" +#include "osal_sem.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct HdfMessageQueue { + struct OsalMutex mutex; + struct OsalSem semaphore; + struct HdfSList list; +}; + +void OsalMessageQueueInit(struct HdfMessageQueue *queue); +void OsalMessageQueueDestroy(struct HdfMessageQueue *queue); +void HdfMessageQueueEnqueue( + struct HdfMessageQueue *queue, struct HdfMessage *message, long delayed); + +struct HdfMessage *HdfMessageQueueNext(struct HdfMessageQueue *queue); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OSAL_MSG_QUEUE_H */ diff --git a/utils/include/osal_sysevent.h b/utils/include/osal_sysevent.h new file mode 100644 index 00000000..b10a74c4 --- /dev/null +++ b/utils/include/osal_sysevent.h @@ -0,0 +1,49 @@ +/* + * 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 OSAL_SYSEVENT_H +#define OSAL_SYSEVENT_H + +#include "hdf_dlist.h" + +#define HDF_SYSEVENT 0xFADE + +/* hdf sys event class definition */ +#define HDF_SYSEVENT_CLASS_POWER 0x00000001 + +/* hdf power event definition */ +enum PowerKeventId { + KEVENT_POWER_SUSPEND, + KEVENT_POWER_DISPLAY_OFF, + KEVENT_POWER_RESUME, + KEVENT_POWER_DISPLAY_ON, + KEVENT_POWER_EVENT_MAX, +}; + +struct HdfSysEvent { + uint64_t eventClass; + uint32_t eventid; + const char *content; + uint64_t syncToken; +}; + +struct HdfSysEventNotifyNode; + +typedef int (*HdfSysEventNotifierFn)( + struct HdfSysEventNotifyNode *self, uint64_t eventClass, uint32_t event, const char *content); + +struct HdfSysEventNotifyNode { + HdfSysEventNotifierFn callback; + struct DListHead listNode; + uint64_t classFilter; +}; + +int HdfSysEventNotifyRegister(struct HdfSysEventNotifyNode *notifierNode, uint64_t classSet); +void HdfSysEventNotifyUnregister(struct HdfSysEventNotifyNode *notifierNode); +int HdfSysEventSend(uint64_t eventClass, uint32_t event, const char *content, bool sync); + +#endif // #ifndef OSAL_SYSEVENT_H \ No newline at end of file diff --git a/utils/src/hdf_map.c b/utils/src/hdf_map.c new file mode 100644 index 00000000..67e14f45 --- /dev/null +++ b/utils/src/hdf_map.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 "hdf_map.h" +#if defined(__KERNEL__) +#include +#else +#include +#endif +#include "osal_mem.h" +#include "securec.h" + +struct MapNode { + uint32_t hash; + uint32_t valueSize; + void *key; + void *value; + struct MapNode *next; +}; + +#define HDF_MIN_MAP_SIZE 8 +#define HDF_ENLARGE_FACTOR 2 +#define HDF_MAP_KEY_MAX_SIZE 1000 +#define HDF_MAP_VALUE_MAX_SIZE 1000 + +const uint32_t HASH_SEED = 131; + +/* BKDR Hash */ +static uint32_t MapHash(const char *hashKey) +{ + uint32_t hashValue = 0; + + while (*hashKey) { + hashValue = hashValue * HASH_SEED + (*hashKey++); + } + + return (hashValue & 0x7FFFFFFF); +} + +static uint32_t MapHashIdx(const Map *map, uint32_t hash) +{ + return (hash & (map->bucketSize - 1)); +} + +static void MapAddNode(Map *map, struct MapNode *node) +{ + uint32_t idx = MapHashIdx(map, node->hash); + node->next = map->nodes[idx]; + map->nodes[idx] = node; +} + +static int32_t MapResize(Map *map, uint32_t size) +{ + uint32_t bucketSize; + struct MapNode **nodes = NULL; + struct MapNode **tmp = NULL; + uint32_t i; + + nodes = (struct MapNode **)OsalMemCalloc(size * sizeof(*nodes)); + if (nodes == NULL) { + return HDF_ERR_MALLOC_FAIL; + } + + tmp = map->nodes; + bucketSize = map->bucketSize; + map->nodes = nodes; + map->bucketSize = size; + + if (tmp != NULL) { + struct MapNode *node = NULL; + struct MapNode *next = NULL; + + /* remap node with new map size */ + for (i = 0; i < bucketSize; i++) { + node = tmp[i]; + while (node != NULL) { + next = node->next; + MapAddNode(map, node); + node = next; + } + } + + OsalMemFree(tmp); + } + + return HDF_SUCCESS; +} + +static struct MapNode *MapCreateNode(const char *key, uint32_t hash, + const void *value, uint32_t valueSize) +{ + uint32_t keySize = strlen(key) + 1; + struct MapNode *node = (struct MapNode *)OsalMemCalloc(sizeof(*node) + keySize + valueSize); + if (node == NULL) { + return NULL; + } + + node->hash = hash; + node->key = (uint8_t *)node + sizeof(*node); + node->value = (uint8_t *)node + sizeof(*node) + keySize; + node->valueSize = valueSize; + if (memcpy_s(node->key, keySize, key, keySize) != EOK) { + OsalMemFree(node); + return NULL; + } + if (memcpy_s(node->value, node->valueSize, value, valueSize) != EOK) { + OsalMemFree(node); + return NULL; + } + + return node; +} + +int32_t MapSet(Map *map, const char *key, const void *value, uint32_t valueSize) +{ + struct MapNode *node = NULL; + + if (map == NULL || key == NULL || value == NULL || valueSize == 0) { + return HDF_ERR_INVALID_PARAM; + } + if (valueSize > HDF_MAP_KEY_MAX_SIZE || strlen(key) > HDF_MAP_VALUE_MAX_SIZE) { + return HDF_ERR_INVALID_PARAM; + } + uint32_t hash = MapHash(key); + if (map->nodeSize > 0 && map->nodes != NULL) { + uint32_t idx = MapHashIdx(map, hash); + node = map->nodes[idx]; + while (node != NULL) { + if (node->hash != hash || node->key == NULL || strcmp(node->key, key) != 0) { + node = node->next; + continue; + } + + // size mismatch + if (node->value == NULL || node->valueSize != valueSize) { + return HDF_ERR_INVALID_OBJECT; + } + // update k-v node + if (memcpy_s(node->value, node->valueSize, value, valueSize) != EOK) { + return HDF_FAILURE; + } + + return HDF_SUCCESS; + } + } + // Increase the bucket size to decrease the possibility of map search conflict. + if (map->nodeSize >= map->bucketSize) { + uint32_t size = (map->bucketSize < HDF_MIN_MAP_SIZE) ? HDF_MIN_MAP_SIZE : \ + (map->bucketSize << HDF_ENLARGE_FACTOR); + MapResize(map, size); + } + + node = MapCreateNode(key, hash, value, valueSize); + if (node == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + MapAddNode(map, node); + map->nodeSize++; + + return HDF_SUCCESS; +} + +void* MapGet(const Map *map, const char *key) +{ + if (map == NULL || key == NULL || map->nodeSize == 0 || map->nodes == NULL) { + return NULL; + } + + uint32_t hash = MapHash(key); + uint32_t idx = MapHashIdx(map, hash); + struct MapNode *node = map->nodes[idx]; + + while (node != NULL) { + if (node->hash == hash && node->key != NULL && !strcmp(node->key, key)) { + return node->value; + } + + node = node->next; + } + + return NULL; +} + +int32_t MapErase(Map *map, const char *key) +{ + if (map == NULL || key == NULL || map->nodeSize == 0 || map->nodes == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + uint32_t hash = MapHash(key); + uint32_t idx = MapHashIdx(map, hash); + struct MapNode *node = map->nodes[idx]; + struct MapNode *prev = node; + + while (node != NULL) { + if (node->hash == hash && node->key != NULL && !strcmp(node->key, key)) { + if (map->nodes[idx] == node) { + map->nodes[idx] = node->next; + } else { + prev->next = node->next; + } + OsalMemFree(node); + map->nodeSize--; + return HDF_SUCCESS; + } + prev = node; + node = node->next; + } + + return HDF_FAILURE; +} + +void MapInit(Map *map) +{ + if (map == NULL) { + return; + } + + map->nodes = NULL; + map->nodeSize = 0; + map->bucketSize = 0; +} + +void MapDelete(Map *map) +{ + uint32_t i; + struct MapNode *node = NULL; + struct MapNode *next = NULL; + + if (map == NULL || map->nodes == NULL) { + return; + } + + for (i = 0; i < map->bucketSize; i++) { + node = map->nodes[i]; + while (node != NULL) { + next = node->next; + OsalMemFree(node); + node = next; + } + } + + OsalMemFree(map->nodes); + + map->nodes = NULL; + map->nodeSize = 0; + map->bucketSize = 0; +} + diff --git a/utils/src/hdf_message_looper.c b/utils/src/hdf_message_looper.c new file mode 100644 index 00000000..b9aa190e --- /dev/null +++ b/utils/src/hdf_message_looper.c @@ -0,0 +1,53 @@ +/* + * 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_message_looper.h" +#include "hdf_message_task.h" +#include "osal_message.h" + +void HdfMessageLooperStart(struct HdfMessageLooper *looper) +{ + struct HdfMessage *message = NULL; + while (looper != NULL) { + message = HdfMessageQueueNext(&looper->messageQueue); + if (message != NULL) { + if (message->messageId == MESSAGE_STOP_LOOP) { + HdfMessageRecycle(message); + OsalMessageQueueDestroy(&looper->messageQueue); + break; + } else if (message->target != NULL) { + struct HdfMessageTask *task = message->target; + task->DispatchMessage(task, message); + } + HdfMessageRecycle(message); + } + } +} + +void HdfMessageLooperStop(struct HdfMessageLooper *looper) +{ + if (looper == NULL) { + return; + } + + struct HdfMessage *message = HdfMessageObtain(0); + if (message != NULL) { + message->messageId = MESSAGE_STOP_LOOP; + HdfMessageQueueEnqueue(&looper->messageQueue, message, 0); + } +} + +void HdfMessageLooperConstruct(struct HdfMessageLooper *looper) +{ + if (looper != NULL) { + OsalMessageQueueInit(&looper->messageQueue); + looper->Start = HdfMessageLooperStart; + looper->Stop = HdfMessageLooperStop; + } +} + diff --git a/utils/src/hdf_message_task.c b/utils/src/hdf_message_task.c new file mode 100644 index 00000000..f8c24c18 --- /dev/null +++ b/utils/src/hdf_message_task.c @@ -0,0 +1,59 @@ +/* + * 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_message_task.h" +#include "hdf_message_looper.h" +#include "osal_mem.h" +#include "osal_message.h" + +int32_t HdfMessageTaskSendMessageLater( + struct HdfMessageTask *task, struct HdfMessage *msg, bool sync, long delay) +{ + if (msg != NULL) { + if (msg->target == NULL) { + msg->target = task; + } + if (sync) { + if (task->messageHandler != NULL && task->messageHandler->Dispatch != NULL) { + int ret = task->messageHandler->Dispatch(task, msg); + OsalMemFree(msg); + return ret; + } + } else { + HdfMessageQueueEnqueue(task->messageQueue, msg, delay); + return HDF_SUCCESS; + } + } + + return HDF_ERR_INVALID_PARAM; +} + +int32_t HdfMessageTaskSendMessage(struct HdfMessageTask *task, struct HdfMessage *msg, bool sync) +{ + return HdfMessageTaskSendMessageLater(task, msg, sync, 0); +} + +void HdfMessageTaskDispatchMessage(struct HdfMessageTask *task, struct HdfMessage *msg) +{ + struct IHdfMessageHandler *handler = task->messageHandler; + if ((handler != NULL) && (handler->Dispatch != NULL)) { + handler->Dispatch(task, msg); + } +} + +void HdfMessageTaskConstruct(struct HdfMessageTask *inst, + struct HdfMessageLooper *looper, struct IHdfMessageHandler *handler) +{ + if (inst != NULL && looper != NULL) { + inst->SendMessage = HdfMessageTaskSendMessage; + inst->messageHandler = handler; + inst->messageQueue = &looper->messageQueue; + inst->DispatchMessage = HdfMessageTaskDispatchMessage; + } +} + diff --git a/utils/src/hdf_slist.c b/utils/src/hdf_slist.c index fdd13671..1aeb396c 100644 --- a/utils/src/hdf_slist.c +++ b/utils/src/hdf_slist.c @@ -23,16 +23,16 @@ bool HdfSListIsEmpty(struct HdfSList *list) return ((list == NULL) || (list->root == NULL)); } -struct HdfSListNode *HdfSListSearch(struct HdfSList *list, uint32_t keyValue, HdfSListSearchCompare compare) +struct HdfSListNode *HdfSListSearch(struct HdfSList *list, uint32_t keyValue, HdfSListSearchComparer comparer) { struct HdfSListIterator it; - if (compare == NULL) { + if (comparer == NULL) { return NULL; } HdfSListIteratorInit(&it, list); while (HdfSListIteratorHasNext(&it)) { struct HdfSListNode *listNode = HdfSListIteratorNext(&it); - if (compare(listNode, keyValue)) { + if (comparer(listNode, keyValue)) { return listNode; } } @@ -47,27 +47,17 @@ struct HdfSListNode *HdfSListGetLast(struct HdfSList *list) return NULL; } - for (iterator = list->root; iterator; iterator = iterator->next) { - if (iterator != NULL) { - last = iterator; - } + for (iterator = list->root; iterator != NULL; iterator = iterator->next) { + last = iterator; } return last; } void HdfSListAdd(struct HdfSList *list, struct HdfSListNode *link) { - struct HdfSListNode *iterator = NULL; if (list == NULL || link == NULL) { return; } - - for (iterator = list->root; iterator; iterator = iterator->next) { - if (iterator == link) { - return; - } - } - link->next = list->root; list->root = link; } @@ -89,10 +79,10 @@ void HdfSListAddTail(struct HdfSList *list, struct HdfSListNode *link) iterator->next = link; } -bool HdfSListAddOrder(struct HdfSList *list, struct HdfSListNode *link, HdfSListAddCompare compare) +bool HdfSListAddOrder(struct HdfSList *list, struct HdfSListNode *link, HdfSListAddComparer comparer) { struct HdfSListNode *iterator = NULL; - if (list == NULL || link == NULL || compare == NULL) { + if (list == NULL || link == NULL || comparer == NULL) { HDF_LOGE("input is invalid"); return false; } @@ -102,13 +92,13 @@ bool HdfSListAddOrder(struct HdfSList *list, struct HdfSListNode *link, HdfSList return false; } } - if (compare(link, list->root)) { + if (comparer(link, list->root)) { link->next = list->root; list->root = link; return true; } for (iterator = list->root; iterator && iterator->next; iterator = iterator->next) { - if (compare(iterator, link) && compare(link, iterator->next)) { + if (comparer(iterator, link) && comparer(link, iterator->next)) { link->next = iterator->next; iterator->next = link; return true; diff --git a/utils/src/hdf_sref.c b/utils/src/hdf_sref.c index 9ea9733a..0df652be 100644 --- a/utils/src/hdf_sref.c +++ b/utils/src/hdf_sref.c @@ -28,6 +28,16 @@ void HdfSRefAcquire(struct HdfSRef *sref) } } +int HdfSRefCount(const struct HdfSRef *sref) +{ + if (sref == NULL) { + HDF_LOGE("invalid sref"); + return 0; + } + + return OsalAtomicRead(&sref->refs); +} + void HdfSRefRelease(struct HdfSRef *sref) { int32_t lockRef; @@ -55,5 +65,6 @@ void HdfSRefConstruct(struct HdfSRef *sref, struct IHdfSRefListener *listener) sref->listener = listener; sref->Acquire = HdfSRefAcquire; sref->Release = HdfSRefRelease; + sref->Count = HdfSRefCount; } diff --git a/utils/src/hdf_thread_ex.c b/utils/src/hdf_thread_ex.c new file mode 100644 index 00000000..ca0f1548 --- /dev/null +++ b/utils/src/hdf_thread_ex.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hdf_thread_ex.h" +#include "osal_mem.h" +#include "osal_thread.h" + +void HdfThreadStart(struct HdfThread *thread) +{ + if (thread == NULL) { + return; + } + struct OsalThreadParam param = { + .priority = OSAL_THREAD_PRI_DEFAULT, + .stackSize = 0, + }; + OsalThreadStart(&thread->adapter, ¶m); + thread->status = true; +} + +void HdfThreadStop(struct HdfThread *thread) +{ + if (thread == NULL) { + return; + } + OsalThreadDestroy(&thread->adapter); + thread->status = false; +} + +bool HdfThreadIsRunning(struct HdfThread *thread) +{ + if (thread == NULL) { + return false; + } + return thread->status; +} + +void HdfThreadMain(void *argv) +{ + struct HdfThread *thread = (struct HdfThread *)argv; + if (thread == NULL) { + return; + } + if (thread->ThreadEntry != NULL) { + thread->ThreadEntry(argv); + } else { + OsalThreadDestroy(&thread->adapter); + } +} + +void HdfThreadConstruct(struct HdfThread *thread) +{ + if (thread == NULL) { + return; + } + thread->Start = HdfThreadStart; + thread->Stop = HdfThreadStop; + thread->IsRunning = HdfThreadIsRunning; + thread->status = false; + OsalThreadCreate(&thread->adapter, (OsalThreadEntry)HdfThreadMain, thread); +} + +void HdfThreadDestruct(struct HdfThread *thread) +{ + if (thread != NULL && thread->IsRunning()) { + thread->Stop(thread); + } +} + +struct HdfThread *HdfThreadNewInstance() +{ + struct HdfThread *thread = + (struct HdfThread *)OsalMemCalloc(sizeof(struct HdfThread)); + if (thread != NULL) { + HdfThreadConstruct(thread); + } + return thread; +} + +void HdfThreadFreeInstance(struct HdfThread *thread) +{ + if (thread != NULL) { + HdfThreadDestruct(thread); + OsalMemFree(thread); + } +} + diff --git a/utils/src/osal_message.c b/utils/src/osal_message.c new file mode 100644 index 00000000..03b756c9 --- /dev/null +++ b/utils/src/osal_message.c @@ -0,0 +1,30 @@ +/* + * 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 "osal_message.h" +#include "osal_mem.h" + +struct HdfMessage *HdfMessageObtain(size_t extendSize) +{ + size_t newSize = sizeof(struct HdfMessage) + extendSize; + return (struct HdfMessage *)OsalMemCalloc(newSize); +} + +void HdfMessageRecycle(struct HdfMessage *message) +{ + OsalMemFree(message); +} + +void HdfMessageDelete(struct HdfSListNode *listEntry) +{ + struct HdfMessage *message = (struct HdfMessage *)listEntry; + if (message != NULL) { + HdfMessageRecycle(message); + } +} + diff --git a/utils/src/osal_msg_queue.c b/utils/src/osal_msg_queue.c new file mode 100644 index 00000000..46445455 --- /dev/null +++ b/utils/src/osal_msg_queue.c @@ -0,0 +1,91 @@ +/* + * 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 "osal_msg_queue.h" +#include "osal_message.h" +#include "osal_time.h" + +void OsalMessageQueueInit(struct HdfMessageQueue *queue) +{ + if (queue != NULL) { + OsalMutexInit(&queue->mutex); + OsalSemInit(&queue->semaphore, 0); + HdfSListInit(&queue->list); + } +} + +void OsalMessageQueueDestroy(struct HdfMessageQueue *queue) +{ + if (queue != NULL) { + OsalMutexDestroy(&queue->mutex); + OsalSemDestroy(&queue->semaphore); + HdfSListFlush(&queue->list, HdfMessageDelete); + } +} + +void HdfMessageQueueEnqueue( + struct HdfMessageQueue *queue, struct HdfMessage *message, long delayed) +{ + if (queue == NULL || message == NULL) { + return; + } + + struct HdfSListIterator it; + (void)delayed; + message->timeStamp += OsalGetSysTimeMs(); + OsalMutexLock(&queue->mutex); + HdfSListIteratorInit(&it, &queue->list); + while (HdfSListIteratorHasNext(&it)) { + struct HdfMessage *next = (struct HdfMessage *)HdfSListIteratorNext(&it); + if (next->timeStamp > message->timeStamp) { + HdfSListIteratorInsert(&it, &message->entry); + goto complete; + } + } + + HdfSListAddTail(&queue->list, &message->entry); +complete: + OsalMutexUnlock(&queue->mutex); + OsalSemPost(&queue->semaphore); +} + +struct HdfMessage* HdfMessageQueueNext(struct HdfMessageQueue *queue) +{ + struct HdfSListIterator it; + struct HdfMessage *message = NULL; + uint64_t currentTime = OsalGetSysTimeMs(); + long miniTimeoutMs = OSAL_WAIT_FOREVER; + OsalMutexLock(&queue->mutex); + HdfSListIteratorInit(&it, &queue->list); + while (HdfSListIteratorHasNext(&it)) { + message = (struct HdfMessage *)HdfSListIteratorNext(&it); + if (message->timeStamp <= currentTime) { + HdfSListIteratorRemove(&it); + OsalMutexUnlock(&queue->mutex); + return message; + } + } + + OsalMutexUnlock(&queue->mutex); + OsalSemWait(&queue->semaphore, miniTimeoutMs); + return NULL; +} + +void HdfMessageQueueFlush(struct HdfMessageQueue *queue) +{ + struct HdfSListIterator it; + OsalMutexLock(&queue->mutex); + HdfSListIteratorInit(&it, &queue->list); + while (HdfSListIteratorHasNext(&it)) { + struct HdfMessage *msgNode = (struct HdfMessage *)HdfSListIteratorNext(&it); + HdfSListIteratorRemove(&it); + HdfMessageRecycle(msgNode); + } + OsalMutexUnlock(&queue->mutex); +} + From c6ce1a770e4f10bc24db34d144e5ef323c486866 Mon Sep 17 00:00:00 2001 From: lzl Date: Tue, 18 May 2021 02:27:10 +0000 Subject: [PATCH 07/21] new mmc code update --- support/platform/include/common/platform.h | 28 + .../platform/include/common/platform_common.h | 90 + .../platform/include/common/platform_device.h | 170 + .../platform/include/common/platform_errno.h | 46 + .../include/common/platform_manager.h | 112 + .../platform/include/common/platform_queue.h | 61 + support/platform/include/mmc/mmc_block.h | 29 + support/platform/include/mmc/mmc_caps.h | 104 + support/platform/include/mmc/mmc_corex.h | 318 ++ support/platform/include/mmc/mmc_dispatch.h | 36 + support/platform/include/mmc/mmc_emmc.h | 44 + support/platform/include/mmc/mmc_protocol.h | 1191 +++++ support/platform/include/mmc/mmc_sd.h | 40 + support/platform/include/mmc/mmc_sdio.h | 106 + support/platform/src/common/platform_common.c | 196 + support/platform/src/common/platform_device.c | 217 + .../platform/src/common/platform_manager.c | 155 + support/platform/src/common/platform_queue.c | 157 + support/platform/src/mmc/emmc_if.c | 159 + support/platform/src/mmc/mmc_block.c | 166 + support/platform/src/mmc/mmc_core.c | 1195 +++++ support/platform/src/mmc/mmc_dispatch.c | 118 + support/platform/src/mmc/mmc_emmc.c | 57 + support/platform/src/mmc/mmc_if.c | 114 + support/platform/src/mmc/mmc_protocol.c | 4119 +++++++++++++++++ support/platform/src/mmc/mmc_sdio.c | 757 +++ support/platform/src/mmc/sdio_if.c | 336 ++ 27 files changed, 10121 insertions(+) create mode 100644 support/platform/include/common/platform.h create mode 100644 support/platform/include/common/platform_common.h create mode 100644 support/platform/include/common/platform_device.h create mode 100644 support/platform/include/common/platform_errno.h create mode 100644 support/platform/include/common/platform_manager.h create mode 100644 support/platform/include/common/platform_queue.h create mode 100644 support/platform/include/mmc/mmc_block.h create mode 100644 support/platform/include/mmc/mmc_caps.h create mode 100644 support/platform/include/mmc/mmc_corex.h create mode 100644 support/platform/include/mmc/mmc_dispatch.h create mode 100644 support/platform/include/mmc/mmc_emmc.h create mode 100644 support/platform/include/mmc/mmc_protocol.h create mode 100644 support/platform/include/mmc/mmc_sd.h create mode 100644 support/platform/include/mmc/mmc_sdio.h create mode 100644 support/platform/src/common/platform_common.c create mode 100644 support/platform/src/common/platform_device.c create mode 100644 support/platform/src/common/platform_manager.c create mode 100644 support/platform/src/common/platform_queue.c create mode 100644 support/platform/src/mmc/emmc_if.c create mode 100644 support/platform/src/mmc/mmc_block.c create mode 100644 support/platform/src/mmc/mmc_core.c create mode 100644 support/platform/src/mmc/mmc_dispatch.c create mode 100644 support/platform/src/mmc/mmc_emmc.c create mode 100644 support/platform/src/mmc/mmc_if.c create mode 100644 support/platform/src/mmc/mmc_protocol.c create mode 100644 support/platform/src/mmc/mmc_sdio.c create mode 100644 support/platform/src/mmc/sdio_if.c diff --git a/support/platform/include/common/platform.h b/support/platform/include/common/platform.h new file mode 100644 index 00000000..dd3a5563 --- /dev/null +++ b/support/platform/include/common/platform.h @@ -0,0 +1,28 @@ +/* + * 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 PLATFORM_H +#define PLATFORM_H + +#include "platform_common.h" +#include "platform_device.h" +#include "platform_manager.h" +#include "platform_queue.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* PLATFORM_H */ diff --git a/support/platform/include/common/platform_common.h b/support/platform/include/common/platform_common.h new file mode 100644 index 00000000..a3d78b6b --- /dev/null +++ b/support/platform/include/common/platform_common.h @@ -0,0 +1,90 @@ +/* + * 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 PLATFORM_COMMON_H +#define PLATFORM_COMMON_H + +#include "hdf_base.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +enum PlatformModuleType { + PLATFORM_MODULE_GPIO, + PLATFORM_MODULE_I2C, + PLATFORM_MODULE_SPI, + PLATFORM_MODULE_PIN, + PLATFORM_MODULE_CLOCK, + PLATFORM_MODULE_REGULATOR, + PLATFORM_MODULE_MIPI_DSI, + PLATFORM_MODULE_UART, + PLATFORM_MODULE_SDIO, + PLATFORM_MODULE_MDIO, + PLATFORM_MODULE_APB, + PLATFORM_MODULE_PCIE, + PLATFORM_MODULE_PCM, + PLATFORM_MODULE_I2S, + PLATFORM_MODULE_PWM, + PLATFORM_MODULE_DMA, + PLATFORM_MODULE_ADC, + PLATFORM_MODULE_RTC, + PLATFORM_MODULE_WDT, + PLATFORM_MODULE_I3C, + PLATFORM_MODULE_CAN, + PLATFORM_MODULE_HDMI, + PLATFORM_MODULE_MMC, + PLATFORM_MODULE_MTD, + PLATFORM_MODULE_DEFAULT, + PLATFORM_MODULE_MAX, +}; + +struct PlatformModuleInfo { + enum PlatformModuleType moduleType; + const char *moduleName; + void *priv; +}; + +struct PlatformModuleInfo *PlatformModuleInfoGet(enum PlatformModuleType moduleType); +int32_t PlatformModuleInfoCount(void); + +enum PlatformErrno { +#define HDF_PLT_ERR_START HDF_BSP_ERR_START /**< Error number start of platform. */ +#define HDF_PLT_ERR_NUM(v) (HDF_PLT_ERR_START + (v)) + HDF_PLT_ERR_OS_API = HDF_ERR_BSP_PLT_API_ERR, + HDF_PLT_ERR_OPEN_DEV = HDF_PAL_ERR_DEV_CREATE, /**< Failed to open a device. */ + HDF_PLT_ERR_INNER = HDF_PAL_ERR_INNER, /**< Internal error of platform framework. */ + + HDF_PLT_ERR_NO_DEV = HDF_PLT_ERR_NUM(-5), /**< There is no device present. */ + HDF_PLT_ERR_DEV_TYPE = HDF_PLT_ERR_NUM(-6), /**< invalid device type */ + HDF_PLT_ERR_DEV_GET = HDF_PLT_ERR_NUM(-7), /**< err on device get */ + HDF_PLT_ERR_DEV_ADD = HDF_PLT_ERR_NUM(-8), /**< err on device add */ + HDF_PLT_ERR_DEV_FULL = HDF_PLT_ERR_NUM(-9), /**< id number conflict */ + HDF_PLT_ERR_ID_REPEAT = HDF_PLT_ERR_NUM(-10), /**< id number conflict */ +#define HDF_MMC_ERR_START (HDF_PLT_ERR_START - 50) /**< Error number start for mmc. */ +#define HDF_MMC_ERR_NUM(v) (HDF_MMC_ERR_START + (v)) + HDF_MMC_ERR_SWITCH_FAIL = HDF_MMC_ERR_NUM(-1), + HDF_MMC_ERR_OTHER_CMD_IS_RUNNING = HDF_MMC_ERR_NUM(-2), + HDF_MMC_ERR_ILLEGAL_SEQ = HDF_MMC_ERR_NUM(-3), +}; + +void PlatformGlobalLock(void); +void PlatformGlobalUnlock(void); + +/* Os adapt */ +bool PlatInIrqContext(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* PLATFORM_COMMON_H */ diff --git a/support/platform/include/common/platform_device.h b/support/platform/include/common/platform_device.h new file mode 100644 index 00000000..d5363b97 --- /dev/null +++ b/support/platform/include/common/platform_device.h @@ -0,0 +1,170 @@ +/* + * 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 PLATFORM_DEVICE_H +#define PLATFORM_DEVICE_H + +#include "hdf_base.h" +#include "hdf_dlist.h" +#include "hdf_sref.h" +#include "osal_sem.h" +#include "osal_spinlock.h" +#include "platform_common.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +struct PlatformManager; + +struct PlatformDevice { + struct HdfDeviceObject *hdfDev; /* releated to an hdf device object */ + struct PlatformManager *manager; /* the platform manager it belongs to */ + uint32_t magic; /* magic number of the device instance */ + const char *name; /* name of the device instance */ + struct HdfSRef ref; /* used for reference count */ + struct DListHead node; /* linked to the list of a manager */ + struct DListHead notifiers; /* list of notifier nodes */ + bool ready; /* indicates whether initialized */ + OsalSpinlock spin; /* for member protection */ + struct OsalSem released; /* for death notification */ +}; + +enum PlatformEventType { + PLAT_EVENT_DEAD = 0, /* a platform device going to die */ +}; + +struct PlatformNotifier { + void *data; /* private data u can take */ + /** + * @brief the event handle funciton of this notifier. + * + * make sure it can be called in irq context. + * + * @param device Indicates the pointer to the platform device. + * @param event Indicates the event type of this handling process. + * + * @since 1.0 + */ + void (*handle)(struct PlatformDevice *device, enum PlatformEventType event, void *data); +}; + +struct PlatformNotifierNode { + struct DListHead node; /* link to notfifier node list */ + struct PlatformNotifier *notifier; /* pointer to the notifier instance */ +}; + +/** + * @brief Initialize a platform device. + * + * Initialize members of a platform device. + * + * @param device Indicates the pointer to the platform device. + * + * @since 1.0 + */ +void PlatformDeviceInit(struct PlatformDevice *device); + +/** + * @brief Uninitialize a platform device. + * + * Uninitialize members of a platform device. + * + * @param device Indicates the pointer to the platform device. + * + * @since 1.0 + */ +void PlatformDeviceUninit(struct PlatformDevice *device); + +/** + * @brief Increase reference count for a platform device. + * + * @param device Indicates the pointer to the platform device. + * + * @return Returns the pointer to the paltform device on success; returns NULL otherwise. + * @since 1.0 + */ +struct PlatformDevice *PlatformDeviceGet(struct PlatformDevice *device); + +/** + * @brief Decrease reference count for a platform device. + * + * @param device Indicates the pointer to the platform device. + * + * @since 1.0 + */ +void PlatformDevicePut(struct PlatformDevice *device); + +/** + * @brief Register a notifier to a platform device. + * + * Subscribe the events of a platform device by registering a notfier. + * + * @param device Indicates the pointer to the platform device. + * @param notifier Indicates the pointer to the platform notifier. + * + * @return Returns 0 if the notifier registered successfully; returns a negative value otherwise. + * @since 1.0 + */ +int32_t PlatformDeviceRegNotifier(struct PlatformDevice *device, struct PlatformNotifier *notifier); + +/** + * @brief Unregister a notifier to a platform device. + * + * Unsubscribe the events of a platform device by unregistering the notfier. + * + * @param device Indicates the pointer to the platform device. + * @param notifier Indicates the pointer to the platform notifier. + * + * @since 1.0 + */ +void PlatformDeviceUnregNotifier(struct PlatformDevice *device, struct PlatformNotifier *notifier); + +/** + * @brief Unregister all notifiers to a platform device. + * + * Unsubscribe all the events of a platform device by clearing the notfiers. + * + * @param device Indicates the pointer to the platform device. + * + * @since 1.0 + */ +void PlatformDeviceClearNotifier(struct PlatformDevice *device); + +/** + * @brief Add a platform device by module type. + * + * do not call in irq context cause can sleep + * + * @param device Indicates the pointer to the platform device. + * + * @return Returns 0 if add successfully; returns a negative value otherwise. + * @since 1.0 + */ +int32_t PlatformDeviceAdd(struct PlatformDevice *device); + +/** + * @brief Remove a platform device by module type. + * + * do not call in irq context cause can sleep + * + * @param device Indicates the pointer to the platform device. + * + * @since 1.0 + */ +void PlatformDeviceDel(struct PlatformDevice *device); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* PLATFORM_DEVICE_H */ diff --git a/support/platform/include/common/platform_errno.h b/support/platform/include/common/platform_errno.h new file mode 100644 index 00000000..edfdbbe5 --- /dev/null +++ b/support/platform/include/common/platform_errno.h @@ -0,0 +1,46 @@ +/* + * 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 PLATFORM_ERRNO_H +#define PLATFORM_ERRNO_H + +#include "hdf_base.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +enum PlatformErrno { +#define HDF_PLT_ERR_START HDF_BSP_ERR_START /**< Error number start of platform. */ +#define HDF_PLT_ERR_NUM(v) (HDF_PLT_ERR_START + (v)) + HDF_PLT_ERR_OS_API = HDF_ERR_BSP_PLT_API_ERR, + HDF_PLT_ERR_OPEN_DEV = HDF_PAL_ERR_DEV_CREATE, /**< Failed to open a device. */ + HDF_PLT_ERR_INNER = HDF_PAL_ERR_INNER, /**< Internal error of platform framework. */ + + HDF_PLT_ERR_NO_DEV = HDF_PLT_ERR_NUM(-5), /**< There is no device present. */ + HDF_PLT_ERR_DEV_TYPE = HDF_PLT_ERR_NUM(-6), /**< invalid device type */ + HDF_PLT_ERR_DEV_GET = HDF_PLT_ERR_NUM(-7), /**< err on device get */ + HDF_PLT_ERR_DEV_ADD = HDF_PLT_ERR_NUM(-8), /**< err on device add */ + HDF_PLT_ERR_DEV_FULL = HDF_PLT_ERR_NUM(-9), /**< id number conflict */ + HDF_PLT_ERR_ID_REPEAT = HDF_PLT_ERR_NUM(-10), /**< id number conflict */ +#define HDF_MMC_ERR_START (HDF_PLT_ERR_START - 50) /**< Error number start for mmc. */ +#define HDF_MMC_ERR_NUM(v) (HDF_MMC_ERR_START + (v)) + HDF_MMC_ERR_SWITCH_FAIL = HDF_MMC_ERR_NUM(-1), + HDF_MMC_ERR_OTHER_CMD_IS_RUNNING = HDF_MMC_ERR_NUM(-2), + HDF_MMC_ERR_ILLEGAL_SEQ = HDF_MMC_ERR_NUM(-3), +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* PLATFORM_ERRNO_H */ diff --git a/support/platform/include/common/platform_manager.h b/support/platform/include/common/platform_manager.h new file mode 100644 index 00000000..8bb1c25d --- /dev/null +++ b/support/platform/include/common/platform_manager.h @@ -0,0 +1,112 @@ +/* + * 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 PLATFORM_MANAGER_H +#define PLATFORM_MANAGER_H + +#include "hdf_base.h" +#include "hdf_dlist.h" +#include "osal_spinlock.h" +#include "platform_device.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +struct PlatformManager { + const char *name; /* name of the manager */ + struct DListHead devices; /* list to keep all it's device instances */ + OsalSpinlock spin; /* for member protection */ +}; + +/** + * @brief Create a platform manager. + * + * Create a platform manager with member initialized. + * + * @param name Indicates the name of the manager. + * + * @return Returns the pointer to the paltform manager on success; returns NULL otherwise. + * @since 1.0 + */ +struct PlatformManager *PlatformManagerCreate(const char *name); + +/** + * @brief Get a platform manager by module type. + * + * @param module Indicates the module type of the manager. + * + * @return Returns the pointer to the paltform manager on success; returns NULL otherwise. + * @since 1.0 + */ +struct PlatformManager *PlatformManagerGet(enum PlatformModuleType module); + +/** + * @brief Add a platform device to a platform manager. + * + * Add a platform device to make it managed by platform core. + * + * @param manager Indicates the pointer to the platform manager. + * @param device Indicates the pointer to the platform device. + * + * @return Returns 0 if the devcie added successfully; returns a negative value otherwise. + * @since 1.0 + */ +int32_t PlatformManagerAddDevice(struct PlatformManager *manager, struct PlatformDevice *device); + +/** + * @brief Remove a platform device from a platform manager. + * + * Remove a platform device to make it away from management of platform core. + * + * @param manager Indicates the pointer to the platform manager. + * @param device Indicates the pointer to the platform device. + * + * @since 1.0 + */ +void PlatformManagerDelDevice(struct PlatformManager *manager, struct PlatformDevice *device); + +/** + * @brief Find a particular device from the manager. + * + * Locate a particular device from the manager by a matching function, witch will be called for + * each device, untill it returns true indicatting a device is "found". + * The device found will be returned with reference count increased. + * + * @param manager Indicates the pointer to the platform manager. + * @param data Indicates the pointer to the data passed to match function. + * @param match Indicates the pointer to the match function. + * + * @return Returns the pointer to the paltform device on success; returns NULL otherwise. + * @since 1.0 + */ +struct PlatformDevice *PlatformManagerFindDevice(struct PlatformManager *manager, void *data, + bool (*match)(struct PlatformDevice *pdevice, void *data)); + +/** + * @brief Get a platform device from the manager by magic. + * + * The device got will be returned with reference count increased. + * + * @param manager Indicates the pointer to the platform manager. + * @param magic Indicates the magic number of the target platform device. + * + * @return Returns the pointer to the paltform device on success; returns NULL otherwise. + * @since 1.0 + */ +struct PlatformDevice *PlatformManagerGetDeviceByMagic(struct PlatformManager *manager, uint32_t magic); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* PLATFORM_MANAGER_H */ diff --git a/support/platform/include/common/platform_queue.h b/support/platform/include/common/platform_queue.h new file mode 100644 index 00000000..00b6839e --- /dev/null +++ b/support/platform/include/common/platform_queue.h @@ -0,0 +1,61 @@ +/* + * 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 PLATFORM_QUEUE_H +#define PLATFORM_QUEUE_H + +#include "hdf_dlist.h" +#include "osal_thread.h" +#include "osal_sem.h" +#include "osal_spinlock.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +struct PlatformMsg; +struct PlatformQueue; + +struct PlatformMsg { + struct DListHead node; + struct OsalSem sem; + int32_t code; + int32_t error; + bool block; /* whether need to block thread */ + void *data; +}; + +int32_t PlatformMsgWait(struct PlatformMsg *msg); +typedef int32_t (*PlatformMsgHandle)(struct PlatformQueue *queue, struct PlatformMsg *msg); + +struct PlatformQueue { + const char *name; + OsalSpinlock spin; + struct OsalSem sem; + struct DListHead msgs; + struct OsalThread thread; /* the worker thread of this queue */ + PlatformMsgHandle handle; + void *data; +}; + +void PlatformQueueAddMsg(struct PlatformQueue *queue, struct PlatformMsg *msg); +struct PlatformQueue *PlatformQueueCreate(PlatformMsgHandle handle, const char *name, void *data); +void PlatformQueueDestroy(struct PlatformQueue *queue); +int32_t PlatformQueueStart(struct PlatformQueue *queue); +int32_t PlatformQueueSuspend(struct PlatformQueue *queue); +int32_t PlatformQueueResume(struct PlatformQueue *queue); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* PLATFORM_QUEUE_H */ diff --git a/support/platform/include/mmc/mmc_block.h b/support/platform/include/mmc/mmc_block.h new file mode 100644 index 00000000..bec2bb78 --- /dev/null +++ b/support/platform/include/mmc/mmc_block.h @@ -0,0 +1,29 @@ +/* + * 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 MMC_BLOCK_H +#define MMC_BLOCK_H + +#include "mmc_corex.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +int32_t MmcBlockAdd(struct MmcDevice *mmc); +void MmcBlockDel(struct MmcDevice *mmc); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* MMC_BLOCK_H */ diff --git a/support/platform/include/mmc/mmc_caps.h b/support/platform/include/mmc/mmc_caps.h new file mode 100644 index 00000000..7f90d063 --- /dev/null +++ b/support/platform/include/mmc/mmc_caps.h @@ -0,0 +1,104 @@ +/* + * 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 MMC_CAPS_H +#define MMC_CAPS_H + +#include "hdf_base.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +enum MmcVolt { VOLT_3V3 = 0, VOLT_1V8, VOLT_1V2 }; + +enum MmcPowerMode { MMC_POWER_MODE_POWER_OFF = 0, MMC_POWER_MODE_POWER_UP, MMC_POWER_MODE_POWER_ON }; + +enum MmcBusWidth { BUS_WIDTH1 = 0, BUS_WIDTH4 = 2, BUS_WIDTH8 = 3 }; + +enum MmcBusTiming { + BUS_TIMING_MMC_DS = 0, + BUS_TIMING_MMC_HS, + BUS_TIMING_SD_HS, + BUS_TIMING_UHS_SDR12, + BUS_TIMING_UHS_SDR25, + BUS_TIMING_UHS_SDR50, + BUS_TIMING_UHS_SDR104, + BUS_TIMING_UHS_DDR50, + BUS_TIMING_UHS_DDR52, + BUS_TIMING_MMC_HS200, /* for emmc */ + BUS_TIMING_MMC_HS400, /* for emmc */ +}; + +union MmcCaps { + uint32_t capsData; + struct CapsBitsData { + uint32_t cap4Bit : 1; /* bit:0 support 4 bit transfer */ + uint32_t cap8Bit : 1; /* bit:1 support 8 bit transfer */ + uint32_t highSpeed : 1; /* bit:2 support high-speed timing */ + uint32_t sdioIrq : 1; /* bit:3 signal pending SDIO irqs */ + uint32_t onlySpi : 1; /* bit:4 only support spi protocols */ + uint32_t needPoll : 1; /* bit:5 need polling for card-detection */ + uint32_t nonremovable : 1; /* bit:6 Nonremoveable eg. eMMC */ + uint32_t waitWhileBusy : 1; /* bit:7 waits while card is busy */ + uint32_t erase : 1; /* bit:8 allow erase */ + uint32_t ddr1v8 : 1; /* bit:9 support ddr mode at 1.8V */ + uint32_t ddr1v2 : 1; /* bit:10 support ddr mode at 1.2V */ + uint32_t powerOffCard : 1; /* bit:11 support power off after boot */ + uint32_t busWidthTest : 1; /* bit:12 CMD14/CMD19 bus width ok */ + uint32_t uhsSdr12 : 1; /* bit:13 support UHS SDR12 mode */ + uint32_t uhsSdr25 : 1; /* bit:14 support UHS SDR25 mode */ + uint32_t uhsSdr50 : 1; /* bit:15 support UHS SDR50 mode */ + uint32_t uhsSdr104 : 1; /* bit:16 support UHS SDR104 mode */ + uint32_t uhsDdr50 : 1; /* bit:17 support UHS DDR50 mode */ + uint32_t xpc330 : 1; /* bit:18 support >150mA current at 3.3V */ + uint32_t xpc300 : 1; /* bit:19 support >150mA current at 3.0V */ + uint32_t xpc180 : 1; /* bit:20 support >150mA current at 1.8V */ + uint32_t driverTypeA : 1; /* bit:21 support driver type A */ + uint32_t driverTypeC : 1; /* bit:22 support driver type C */ + uint32_t driverTypeD : 1; /* bit:23 support driver type D */ + uint32_t maxCurrentLimit200 : 1; /* bit:24 max current limit 200mA */ + uint32_t maxCurrentLimit400 : 1; /* bit:25 max current limit 400mA */ + uint32_t maxCurrentLimit600 : 1; /* bit:26 max current limit 600mA */ + uint32_t maxCurrentLimit800 : 1; /* bit:27 max current limit 800mA */ + uint32_t cmd23 : 1; /* bit:28 support CMD23 */ + uint32_t hardwareReset : 1; /* bit:29 support hardware reset */ + uint32_t sdSupportProtocol3 : 1; /* bit:30 SD support Protocol 3.0 */ + uint32_t cmdStop : 1; /* bit:31 support cmd stop */ + } bits; +}; + +union MmcCaps2 { + uint32_t caps2Data; + struct Caps2BitsData { + uint32_t bootPartNoAcc : 1; /* bit:0 boot partition no access */ + uint32_t cacheCtrl : 1; /* bit:1 allow cache control */ + uint32_t poweroffNotify : 1; /* bit:2 support notify power off */ + uint32_t noMultiRead : 1; /* bit:3 not support multiblock read */ + uint32_t noSleepCmd : 1; /* bit:4 not support sleep command */ + uint32_t hs200Sdr1v8 : 1; /* bit:5 support hs200 sdr 1.8V */ + uint32_t hs200Sdr1v2 : 1; /* bit:6 support sdr hs200 1.2V */ + uint32_t brokenVoltage : 1; /* bit:7 use broken voltage */ + uint32_t detectNoErr : 1; /* bit:8 I/O err check card removal */ + uint32_t hcEraseSize : 1; /* bit:9 High-capacity erase size */ + uint32_t hs400Support1v8 : 1; /* bit:10 support hs400 1.8V */ + uint32_t hs400Support1v2 : 1; /* bit:11 support hs400 1.2V */ + uint32_t hs400EnhancedStrobe : 1; /* bit:12 support hs400 enhanced strobe */ + uint32_t reserved : 18; /* bits:13~31, reserved */ + } bits; +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* _MMC_CAPS_H */ diff --git a/support/platform/include/mmc/mmc_corex.h b/support/platform/include/mmc/mmc_corex.h new file mode 100644 index 00000000..6cdd2d0a --- /dev/null +++ b/support/platform/include/mmc/mmc_corex.h @@ -0,0 +1,318 @@ +/* + * 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 MMC_CORE_H +#define MMC_CORE_H + +#include "hdf_base.h" +#include "hdf_device_desc.h" +#include "hdf_log.h" +#include "mmc_caps.h" +#include "mmc_protocol.h" +#include "osal_mem.h" +#include "osal_mutex.h" +#include "osal_time.h" +#include "platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#define MMC_CNTLR_NR_MAX 3 +#define MMC_DEV_NR_MAX 3 +#define MMC_SEC_SIZE 512 + +#define MMC_MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MMC_MAX(x, y) (((x) < (y)) ? (y) : (x)) + +struct MmcCntlr; +struct MmcCntlrOps; +struct MmcDevice; +struct MmcMsg; +struct MmcData; +struct MmcCmd; +enum MmcMsgCode; +enum MmcCmdCode; +union MmcDevState; + +enum MmcDevType { + MMC_DEV_EMMC = 0, + MMC_DEV_SD, + MMC_DEV_SDIO, + MMC_DEV_COMBO, + MMC_DEV_INVALID +}; + +struct MmcCntlr { + struct IDeviceIoService service; + struct HdfDeviceObject *hdfDevObj; + struct PlatformDevice device; + struct OsalMutex mutex; + struct OsalSem released; + uint32_t devType; + struct MmcDevice *curDev; + struct MmcCntlrOps *ops; + struct PlatformQueue *msgQueue; + uint16_t index; + uint16_t voltDef; + uint32_t vddBit; + uint32_t freqMin; + uint32_t freqMax; + uint32_t freqDef; + union MmcOcr ocrDef; + union MmcCaps caps; + union MmcCaps2 caps2; + uint32_t maxBlkNum; + uint32_t maxBlkSize; + uint32_t maxReqSize; + bool devPluged; + bool detecting; + void *priv; +}; + +struct MmcCntlrOps { + int32_t (*request)(struct MmcCntlr *cntlr, struct MmcCmd *cmd); + int32_t (*setClock)(struct MmcCntlr *cntlr, uint32_t clock); + int32_t (*setPowerMode)(struct MmcCntlr *cntlr, enum MmcPowerMode mode); + int32_t (*setBusWidth)(struct MmcCntlr *cntlr, enum MmcBusWidth width); + int32_t (*setBusTiming)(struct MmcCntlr *cntlr, enum MmcBusTiming timing); + int32_t (*setSdioIrq)(struct MmcCntlr *cntlr, bool enable); + int32_t (*hardwareReset)(struct MmcCntlr *cntlr); + int32_t (*systemInit)(struct MmcCntlr *cntlr); + int32_t (*setEnhanceSrobe)(struct MmcCntlr *cntlr, bool enable); + int32_t (*switchVoltage)(struct MmcCntlr *cntlr, enum MmcVolt volt); + bool (*devReadOnly)(struct MmcCntlr *cntlr); + bool (*devPluged)(struct MmcCntlr *cntlr); + bool (*devBusy)(struct MmcCntlr *cntlr); + int32_t (*tune)(struct MmcCntlr *cntlr, uint32_t cmdCode); + int32_t (*rescanSdioDev)(struct MmcCntlr *cntlr); +}; + +/* controller management */ +int32_t MmcCntlrAdd(struct MmcCntlr *cntlr); +void MmcCntlrRemove(struct MmcCntlr *cntlr); +struct MmcDevice *MmcCntlrGetDevice(struct MmcCntlr *cntlr); + +static inline struct MmcCntlr *MmcCntlrGet(struct MmcCntlr *cntlr) +{ + if (cntlr != NULL && PlatformDeviceGet(&cntlr->device) != NULL) { + return cntlr; + } + return NULL; +} + +static inline struct MmcCntlr *MmcCntlrGetByNr(uint16_t number) +{ + struct PlatformDevice *device = PlatformManagerGetDeviceByMagic(PlatformManagerGet(PLATFORM_MODULE_MMC), number); + + if (device == NULL) { + return NULL; + } + return CONTAINER_OF(device, struct MmcCntlr, device); +} + +static inline void MmcCntlrPut(struct MmcCntlr *cntlr) +{ + if (cntlr != NULL) { + PlatformDevicePut(&cntlr->device); + } +} + +static inline bool MmcCntlrDevPresent(struct MmcCntlr *cntlr) +{ + return (cntlr != NULL && cntlr->curDev != NULL); +} + +static inline void MmcCntlrLock(struct MmcCntlr *cntlr) +{ + if (cntlr != NULL) { + (void)OsalMutexLock(&cntlr->mutex); + } +} + +static inline void MmcCntlrUnlock(struct MmcCntlr *cntlr) +{ + if (cntlr != NULL) { + (void)OsalMutexUnlock(&cntlr->mutex); + } +} + +/* controller common bussiness */ +int32_t MmcCntlrDoRequest(struct MmcCntlr *cntlr, struct MmcCmd *cmd); +int32_t MmcCntlrAddMsgToQueue(struct MmcCntlr *cntlr, struct MmcCmd *cmd, int32_t code, bool block); +int32_t MmcCntlrAddRequestMsgToQueue(struct MmcCntlr *cntlr, struct MmcCmd *cmd); +int32_t MmcCntlrAddDetectMsgToQueue(struct MmcCntlr *cntlr); +int32_t MmcCntlrAddPlugMsgToQueue(struct MmcCntlr *cntlr); +int32_t MmcCntlrAddSdioRescanMsgToQueue(struct MmcCntlr *cntlr); +int32_t MmcCntlrParse(struct MmcCntlr *cntlr, struct HdfDeviceObject *obj); +int32_t MmcCntlrCreatSdioIrqThread(struct MmcCntlr *cntlr); +void MmcCntlrDestroySdioIrqThread(struct MmcCntlr *cntlr); +void MmcCntlrNotifySdioIrqThread(struct MmcCntlr *cntlr); + +/* controller private bussiness */ +void MmcCntlrSetClock(struct MmcCntlr *cntlr, uint32_t clock); +void MmcCntlrSetBusWidth(struct MmcCntlr *cntlr, enum MmcBusWidth width); +void MmcCntlrSetBusTiming(struct MmcCntlr *cntlr, enum MmcBusTiming timing); +void MmcCntlrSetEnhanceSrobe(struct MmcCntlr *cntlr, bool enable); +int32_t MmcCntlrSwitchVoltage(struct MmcCntlr *cntlr, enum MmcVolt voltage); +bool MmcCntlrDevReadOnly(struct MmcCntlr *cntlr); +bool MmcCntlrDevBusy(struct MmcCntlr *cntlr); +bool MmcCntlrDevPluged(struct MmcCntlr *cntlr); +int32_t MmcCntlrTune(struct MmcCntlr *cntlr, uint32_t cmdCode); +void MmcCntlrSelectWorkVoltage(struct MmcCntlr *cntlr, union MmcOcr *ocr); +void MmcCntlrPowerUp(struct MmcCntlr *cntlr); +void MmcCntlrPowerOff(struct MmcCntlr *cntlr); +int32_t MmcCntlrAllocDev(struct MmcCntlr *cntlr, enum MmcDevType devType); +void MmcCntlrFreeDev(struct MmcCntlr *cntlr); +bool MmcCntlrSupportUhs(struct MmcCntlr *cntlr); +bool MmcCntlrSupportHighSpeed400EnhancedStrobe(struct MmcCntlr *cntlr); +bool MmcCntlrSupportHighSpeed400(struct MmcCntlr *cntlr); +bool MmcCntlrSupportHighSpeed200(struct MmcCntlr *cntlr); +bool MmcCntlrSdSupportCmd23(struct MmcCntlr *cntlr); +bool MmcCntlrEmmcSupportCmd23(struct MmcCntlr *cntlr); + +struct MmcDeviceWorkParam { + uint32_t clock; + enum MmcBusWidth width; + enum MmcBusTiming timing; +}; + +struct MmcRegister { + union MmcOcr ocr; + uint32_t rca; + uint32_t rawCid[CID_LEN]; + uint32_t rawCsd[CSD_LEN]; + struct MmcCid cid; + struct MmcCsd csd; +}; + +union MmcDevState { + uint32_t stateData; + struct StateBitsData { + uint32_t present : 1; + uint32_t readonly : 1; + uint32_t highSpeed : 1; + uint32_t blockAddr : 1; + uint32_t ddrMode : 1; + uint32_t highSpeedDdr : 1; + uint32_t uhs : 1; + uint32_t sdxc : 1; + uint32_t hs200 : 1; + uint32_t sleep : 1; + uint32_t removeable : 1; + uint32_t blkszForByteMode : 1; + uint32_t hs400 : 1; + uint32_t hs400es : 1; + uint32_t reserverd : 17; + } bits; +}; + +struct MmcDevice { + struct PlatformDevice device; + struct MmcCntlr *cntlr; + struct MmcRegister reg; + struct MmcDeviceWorkParam workPara; + union MmcDevState state; + enum MmcDevType type; + size_t secSize; // by bytes + size_t capacity; // by sectors + size_t eraseSize; // by sectors + struct StorageBlock *sb; + void *priv; +}; + +/* device management */ +int32_t MmcDeviceAdd(struct MmcDevice *mmc); +void MmcDeviceAddOps(struct MmcDevice *mmc, void *ops); +void MmcDeviceRemove(struct MmcDevice *mmc); +struct MmcDevice *MmcDeviceGet(struct MmcDevice *mmc); +void MmcDevicePut(struct MmcDevice *mmc); + +/* device business */ +ssize_t MmcDeviceRead(struct MmcDevice *mmc, uint8_t *buf, size_t startSec, size_t nSec); +ssize_t MmcDeviceWrite(struct MmcDevice *mmc, uint8_t *buf, size_t startSec, size_t nSec); +ssize_t MmcDeviceErase(struct MmcDevice *mmc, size_t startSec, size_t nSec); + +static inline bool MmcDeviceIsPresent(struct MmcDevice *mmc) +{ + return (mmc != NULL && mmc->state.bits.present); +} + +struct MmcCmd { + uint32_t cmdCode; + uint32_t argument; + uint32_t resp[MMC_CMD_RESP_SIZE]; + uint32_t respType; + int32_t returnError; + struct MmcData *data; +}; + +#define DATA_WRITE (0x1 << 0) +#define DATA_READ (0x1 << 1) +#define DATA_STREAM (0x1 << 2) +struct MmcData { + uint32_t blockSize; /* data block size, byte */ + uint32_t blockNum; + int32_t returnError; + uint8_t *dataBuffer; + void *scatter; + uint32_t scatterLen; + uint32_t dataFlags; + struct MmcCmd stopCmd; /* stop command */ + bool sendStopCmd; +}; + +enum MmcMsgCode { + MMC_MSG_REQUEST, + MMC_MSG_PLUG, + MMC_MSG_UNPLUG, + MMC_MSG_SDIO_RESCAN, +}; + +struct MmcMsg { + struct PlatformMsg msg; + struct MmcCmd *mmcCmd; +}; + +struct MmcRwData { + uint8_t *buf; + bool writeFlag; + size_t startSector; + size_t sectors; +}; + +int32_t MmcDoDetect(struct MmcCntlr *cntlr); +void MmcDeleteDev(struct MmcCntlr *cntlr); +int32_t MmcSendStatus(struct MmcCntlr *cntlr, uint32_t *status); +int32_t MmcStopTransmission(struct MmcCntlr *cntlr, bool writeFlag, uint32_t *stopStatus); +int32_t MmcSendTuning(struct MmcCntlr *cntlr, uint32_t cmdCode, bool sendStop); +int32_t MmcSendErase(struct MmcCntlr *cntlr, uint32_t startSec, uint32_t nSec); +void MmcSetupReadWriteBlocksCmd(struct MmcDevice *mmc, struct MmcCmd *cmd, struct MmcRwData *info); +int32_t MmcSendReadWriteBlocks(struct MmcCntlr *cntlr, struct MmcRwData *info); +int32_t SdioReinit(struct MmcCntlr *cntlr); +int32_t SdioReadCccrIoEnable(struct MmcCntlr *cntlr, uint8_t *val); +int32_t SdioCccrIntEnable(struct MmcCntlr *cntlr); +int32_t SdioCccrIntDisable(struct MmcCntlr *cntlr); +int32_t SdioCccrIoEnable(struct MmcCntlr *cntlr); +int32_t SdioCccrIoDisable(struct MmcCntlr *cntlr); +int32_t SdioReadCccrIntPending(struct MmcCntlr *cntlr, uint8_t *val); +int32_t SdioReadCccrIoReady(struct MmcCntlr *cntlr, uint8_t *val); +int32_t SdioSetFbrIoBlockSize(struct MmcCntlr *cntlr, uint32_t blkSize); +int32_t SdioReadWriteByte(struct MmcCntlr *cntlr, bool writeFlag, + uint32_t funcNum, uint32_t addr, uint8_t *data); +int32_t SdioReadWriteBlock(struct MmcCntlr *cntlr, struct SdioRwBlockInfo *info); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* MMC_CORE_H */ diff --git a/support/platform/include/mmc/mmc_dispatch.h b/support/platform/include/mmc/mmc_dispatch.h new file mode 100644 index 00000000..51db247a --- /dev/null +++ b/support/platform/include/mmc/mmc_dispatch.h @@ -0,0 +1,36 @@ +/* + * 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 MMC_DISPATCH_H +#define MMC_DISPATCH_H + +#ifndef __USER__ +#include "devsvc_manager_clnt.h" +#endif + +#ifdef __USER__ +#include "hdf_io_service_if.h" +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#ifndef __USER__ +int32_t MmcIoDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply); +#endif + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* MMC_DISPATCH_H */ diff --git a/support/platform/include/mmc/mmc_emmc.h b/support/platform/include/mmc/mmc_emmc.h new file mode 100644 index 00000000..dadfec8a --- /dev/null +++ b/support/platform/include/mmc/mmc_emmc.h @@ -0,0 +1,44 @@ +/* + * 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 MMC_EMMC_H +#define MMC_EMMC_H + +#include "emmc_if.h" +#include "mmc_corex.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +struct EmmcRegister { + struct EmmcExtCsd extCsd; +}; + +struct EmmcDevice { + struct MmcDevice mmc; + struct EmmcDeviceOps *emmcOps; + struct EmmcRegister emmcReg; +}; + +struct EmmcDeviceOps { + int32_t (*getCid)(struct EmmcDevice *, uint8_t *, uint32_t); +}; + +int32_t EmmcDeviceGetCid(struct EmmcDevice *dev, uint8_t *cid, uint32_t len); +void EmmcDeviceAddOps(struct EmmcDevice *dev, void *ops); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* MMC_EMMC_H */ diff --git a/support/platform/include/mmc/mmc_protocol.h b/support/platform/include/mmc/mmc_protocol.h new file mode 100644 index 00000000..96567b27 --- /dev/null +++ b/support/platform/include/mmc/mmc_protocol.h @@ -0,0 +1,1191 @@ +/* + * 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 MMC_PROTOCOL_H +#define MMC_PROTOCOL_H + +#include "hdf_base.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#define CID_LEN 4 +#define CID_BITS 128 +#define CID_BYTES_LEN 16 +#define CID_PNM_LEN 8 +#define CSD_LEN 4 +#define CSD_BITS 128 +#define EXT_CSD_BYTES_LEN 512 +#define BITS_PER_BYTE 8 +#define SCR_LEN 2 +#define SCR_BYTES_LEN 8 +#define SCR_BITS 64 +#define DSR_BITS 16 +#define SSR_LEN 16 +#define SSR_BYTES_LEN 64 +#define SSR_BITS 512 + +/* The basic unit data transfer is a block whose maximum size is always 512 bytes. */ +#define BYTES_PER_BLOCK 512 +#define MMC_MAX_BLOCKSIZE_SHIFT 9 + +#define SDIO_BLOCK_TRANSFER_MAX_BLKNUM 511 + +/* mmc commands */ +enum MmcCmdCode { + GO_IDLE_STATE = 0, /* resets all cards to idle state */ + SEND_OP_COND = 1, /* + * asks all cards in idle state to send their operation conditions register contents + * in the response on the CMD line. + */ + ALL_SEND_CID = 2, /* asks all cards to send their CID numbers on the CMD line. */ + SET_RELATIVE_ADDR = 3, /* assigns relative address to the card. */ + SET_DSR = 4, /* programs the DSR of all cards. */ + SWITCH = 6, /* Switches the mode of operation of the selected card or modifies the EXT_CSD registers. */ + SELECT_CARD = 7, /* + * command toggles a card between the stand-by and transfer states or between the programming and + * disconnect states. In both cases the card is selected by its own relative address and gets + * deselected by any other address; address 0 deselects all. + */ + SEND_EXT_CSD = 8, /* The card sends its EXT_CSD register as a block of data. */ + SEND_CSD = 9, /* addressed card sends its card-specific data (CSD) on the CMD line. */ + SEND_CID = 10, /* addressed card sends its card identification (CID) on CMD the line. */ + READ_DAT_UNTIL_STOP = 11, /* + * reads data stream from the card, starting at the given address, + * until a STOP_TRANSMISSION follows. + */ + STOP_TRANSMISSION = 12, /* + * Terminates a read/write stream/multiple block operation. + * When CMD12 is used to terminate a read transaction the card will respond with R1. + * When it is used to stop a write transaction the card will respondwith R1b. + */ + SEND_STATUS = 13, /* addressed card sends its status register. */ + GO_INACTIVE_STATE = 15, /* + * sets the card to inactive state in order to protect the card stack against + * communication breakdowns. + */ + SET_BLOCKLEN = 16, /* + * sets the block length (in bytes) for all following block commands (read and write). + * Default block length is specified in the CSD. + */ + READ_SINGLE_BLOCK = 17, /* reads a block of the size selected by the SET_BLOCKLEN command. */ + READ_MULTIPLE_BLOCK = 18, /* + * continuously transfers data blocks from card to host until interrupted + * by a stop command or the requested number of data block transmitted. + */ + WRITE_DAT_UNTIL_STOP = 20, /* + * writes data stream from the host, starting at the given address, + * until a STOP_TRANSMISSION follows. + */ + SEND_TUNING_BLOCK_HS200 = 21, /* + * Dedicated for HS200 mode, used to optimize host sampling points. + * The host sends the CMD21 command, and the device sends the data block in tuning + * mode. The host collects data at different sampling points to find the best + * sampling point. + */ + SET_BLOCK_COUNT = 23, /* + * Defines the number of blocks which are going to be transferred in the immediately + * succeeding multiple block read or write command. + */ + WRITE_BLOCK = 24, /* writes a block of the size selected by the SET_BLOCKLEN command. */ + WRITE_MULTIPLE_BLOCK = 25, /* + * continuously writes blocks of data until a STOP_TRANSMISSION follows + * or the requested number of block received. + */ + PROGRAM_CID = 26, /* + * programming of the card identification register. This command shall be issued only once + * per card. The card contains hardware to prevent this operation after the first programming. + * Normally this command is reserved for the manufacturer. + */ + PROGRAM_CSD = 27, /* programming of the programmable bits of the CSD. */ + SET_WRITE_PROT = 28, /* + * if the card has write protection features, + * this command sets the write protection bit of the addressed group. + * The properties of write protection are coded in the card specific data (WP_GRP_SIZE). + */ + CLR_WRITE_PROT = 29, /* + * if the card provides write protection features, + * this command clears the write protection bit of the addressed group. + */ + SEND_WRITE_PROT = 30, /* + * if the card provides write protection features, + * this command asks the card to send the status of the write protection bits. + */ + ERASE_GROUP_START = 35, /* sets the address of the first erase group within a range to be selected for erase. */ + ERASE_GROUP_END = 36, /* + * sets the address of the last erase group within a continuous + * range to be selected for erase. + */ + MMC_ERASE = 38, /* erases all previously selected write blocks. */ + MMC_FAST_IO = 39, /* + * used to write and read 8 bit (register) data fields. The command addresses a card and + * a register and provides the data for writing if the write flag is set. The R4 response + * contains data read from the addressed register. This command accesses application + * dependent registers which are not defined in the MultiMediaCard standard. + */ + GO_IRQ_STATE = 40, /* Sets the system into interrupt mode. */ + LOCK_UNLOCK = 42, /* + * Used to set/reset the password or lock/ unlock the card. + * The size of the data block is set by the SET_BLOCK_LEN command. + */ + APP_CMD = 55, /* + * Indicates to the card that the next command is an application specific command + * rather than a standard command. + */ + GEN_CMD = 56, /* + * Used either to transfer a data block to the card or to get a data block from the card + * for general purpose / application specific commands. + * The size of the data block shall be set by the SET_BLOCK_LEN command. + */ +}; + +#define MMC_CARD_BUSY_STATUS 0x80000000 /* Card Power up status bit */ + +/* OCR bit definitions */ +enum MmcOcrBitsMark { + MMC_OCR_1V65_1V95 = 0x00000080, /* VDD 1.65V ~ 1.95V */ + MMC_OCR_2V0_2V1 = 0x00000100, /* VDD 2.0V ~ 2.1V */ + MMC_OCR_2V1_2V2 = 0x00000200, /* VDD 2.1V ~ 2.2V */ + MMC_OCR_2V2_2V3 = 0x00000400, /* VDD 2.2V ~ 2.3V */ + MMC_OCR_2V3_2V4 = 0x00000800, /* VDD 2.3V ~ 2.4V */ + MMC_OCR_2V4_2V5 = 0x00001000, /* VDD 2.4V ~ 2.5V */ + MMC_OCR_2V5_2V6 = 0x00002000, /* VDD 2.5V ~ 2.6V */ + MMC_OCR_2V6_2V7 = 0x00004000, /* VDD 2.6V ~ 2.7V */ + MMC_OCR_2V7_2V8 = 0x00008000, /* VDD 2.7V ~ 2.8V */ + MMC_OCR_2V8_2V9 = 0x00010000, /* VDD 2.8V ~ 2.9V */ + MMC_OCR_2V9_3V0 = 0x00020000, /* VDD 2.9V ~ 3.0V */ + MMC_OCR_3V0_3V1 = 0x00040000, /* VDD 3.0V ~ 3.1V */ + MMC_OCR_3V1_3V2 = 0x00080000, /* VDD 3.1V ~ 3.2V */ + MMC_OCR_3V2_3V3 = 0x00100000, /* VDD 3.2V ~ 3.3V */ + MMC_OCR_3V3_3V4 = 0x00200000, /* VDD 3.3V ~ 3.4V */ + MMC_OCR_3V4_3V5 = 0x00400000, /* VDD 3.4V ~ 3.5V */ + MMC_OCR_3V5_3V6 = 0x00800000, /* VDD 3.5V ~ 3.6V */ +}; + +/* ocr register describe */ +union MmcOcr { + uint32_t ocrData; + struct OcrBits { + uint32_t reserved : 7; + uint32_t vdd1v65To1v95 : 1; /* bit:7 voltage 1.65 ~ 1.95 */ + uint32_t vdd2v0To2v1 : 1; /* bit:8 voltage 2.0 ~ 2.1 */ + uint32_t vdd2v1To2v2 : 1; /* bit:9 voltage 2.1 ~ 2.2 */ + uint32_t vdd2v2To2v3 : 1; /* bit:10 voltage 2.2 ~ 2.3 */ + uint32_t vdd2v3To2v4 : 1; /* bit:11 voltage 2.3 ~ 2.4 */ + uint32_t vdd2v4To2v5 : 1; /* bit:12 voltage 2.4 ~ 2.5 */ + uint32_t vdd2v5To2v6 : 1; /* bit:13 voltage 2.5 ~ 2.6 */ + uint32_t vdd2v6To2v7 : 1; /* bit:14 voltage 2.6 ~ 2.7 */ + uint32_t vdd2v7To2v8 : 1; /* bit:15 voltage 2.7 ~ 2.8 */ + uint32_t vdd2v8To2v9 : 1; /* bit:16 voltage 2.8 ~ 2.9 */ + uint32_t vdd2v9To3v0 : 1; /* bit:17 voltage 2.9 ~ 3.0 */ + uint32_t vdd3v0To3v1 : 1; /* bit:18 voltage 3.0 ~ 3.1 */ + uint32_t vdd3v1To3v2 : 1; /* bit:19 voltage 3.1 ~ 3.2 */ + uint32_t vdd3v2To3v3 : 1; /* bit:20 voltage 3.2 ~ 3.3 */ + uint32_t vdd3v3To3v4 : 1; /* bit:21 voltage 3.3 ~ 3.4 */ + uint32_t vdd3v4To3v5 : 1; /* bit:22 voltage 3.4 ~ 3.5 */ + uint32_t vdd3v5To3v6 : 1; /* bit:23 voltage 3.5 ~ 3.6 */ + uint32_t s18r : 1; /* bit:24 switch to 1.8v accepted */ + uint32_t reserved2 : 2; + uint32_t sdioMemoryPreset : 1; /* bit:27 sdio memory present */ + uint32_t sdXpc : 1; /* bit:28 XPC for ACMD41 */ + uint32_t sdUhsII : 1; /* bit:29 UHSII for resp of ACMD41 */ + uint32_t hcs : 1; /* bit:30 support high capacity */ + uint32_t busy : 1; /* bit:31 This bit is set to LOW if the card has not finished the power up routine */ + } bits; +}; + +/* SEND_STATUS rsp, card status bits */ +enum MmcRspCardStatus { + OUT_OF_RANGE = (1 << 31), /* The command's argument was out of the allowed range for this card. */ + ADDRESS_ERROR = (1 << 30), /* A misaligned address which did not match the block length was used in the command. */ + BLOCK_LEN_ERROR = (1 << 29), /* The transferred block length is not allowed for this card, + * or the number of transferred bytes does not match the block length. + */ + ERASE_SEQ_ERROR = (1 << 28), /* An error in the sequence of erase commands occurred. */ + ERASE_PARAM = (1 << 27), /* An invalid selection of erase groups for erase occurred. */ + WP_VIOLATION = (1 << 26), /* Attempt to program a write protected block. */ + CARD_IS_LOCKED = (1 << 25), /* When set, signals that the card is locked by the host. */ + LOCK_UNLOCK_FAILED = (1 << 24), /* Set when a sequence or password error has been detected in lock/unlock card + * command or if there was an attempt to access a locked card. + */ + COM_CRC_ERROR = (1 << 23), /* The CRC check of the previous command failed. */ + ILLEGAL_COMMAND = (1 << 22), /* Command not legal for the card state. */ + CARD_ECC_FAILED = (1 << 21), /* Card internal ECC was applied but failed to correct the data. */ + CC_ERROR = (1 << 20), /* Internal card controller error. */ + GENERAL_ERROR = (1 << 19), /* A general or an unknown error occurred during the operation. */ + UNDERRUN = (1 << 18), /* The card could not sustain data transfer in stream read mode. */ + OVERRUN = (1 << 17), /* The card could not sustain data programming in stream write mode. */ + CID_CSD_OVERWRITE = (1 << 16), /* can be either one of the following errors: + * - The CID register has been already written and can not be overwritten + * - The read only section of the CSD does not match the card content. + * - An attempt to reverse the copy (set as original) or permanent WP (unprotected) + * bits was made. + */ + WP_ERASE_SKIP = (1 << 15), /* Only partial address space was erased due to existing write protected blocks. */ + CARD_ECC_DISABLED = (1 << 14), /* The command has been executed without using the internal ECC. */ + ERASE_RESET = (1 << 13), /* An erase sequence was cleared before executing because an out of erase sequence + * command was received. + */ + READY_FOR_DATA = (1 << 8), /* corresponds to buffer empty signalling on the bus. */ + SWITCH_ERROR = (1 << 7), /* If set, the card did not switch to the expected mode as requested by + * the SWITCH command. + */ + URGENT_BKOPS = (1 << 6), /* If set, device needs to perform background operations urgently. + * Host can check EXT_CSD field BKOPS_STATUS for the detailed level. + */ + IS_APP_CMD = (1 << 5), /* The card will expect ACMD, or indication that the command has been + * interpreted as ACMD. + */ +}; + +/* + * The state of the card when receiving the command. If the command execution causes a + * state change, it will be visible to the host in the response to the next command. + * The four bits([12:9]) are interpreted as a binary coded number between 0 and 15. + */ +#define MMC_CARD_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ +enum MmcCardCurrentState { + STATE_IDLE = 0, + STATE_READY = 1, + STATE_IDENT = 2, + STATE_STBY = 3, + STATE_TRAN = 4, + STATE_DATA = 5, + STATE_RCV = 6, + STATE_PRG = 7, + STATE_DIS = 8, +}; + +/* addressed (point-to-point) commands (ac) sent on CMD line, response on CMD line. */ +#define MMC_CMD_TYPE_AC (0x0 << 5) + +/* + * addressed (point-to-point) data transfer commands (adtc) sent on CMD line, response on CMD line, + * data transfer on DAT line. + */ +#define MMC_CMD_TYPE_ADTC (0x1 << 5) + +/* broadcast commands (bc) sent on CMD line, no response. */ +#define MMC_CMD_TYPE_BC (0x2 << 5) + +/* broadcast commands with response (bcr) sent on CMD line, response (all cards simultaneously) on CMD line. */ +#define MMC_CMD_TYPE_BCR (0x3 << 5) + +#define MMC_CMD_RESP_SIZE 4 +/* cmd resp type */ +#define RESP_PRESENT (1 << 0) +#define RESP_136 (1 << 1) /* 136 bit response */ +#define RESP_CRC (1 << 2) /* expect valid crc */ +#define RESP_BUSY (1 << 3) /* card may send busy */ +#define RESP_CMDCODE (1 << 4) /* response contains opcode */ + +#define MMC_RESP_NONE 0 +#define MMC_RESP_R1 (RESP_PRESENT | RESP_CMDCODE | RESP_CRC) +#define MMC_RESP_R1B (RESP_PRESENT | RESP_CMDCODE | RESP_BUSY | RESP_CRC) +#define MMC_RESP_R2 (RESP_PRESENT | RESP_136 | RESP_CRC) +#define MMC_RESP_R3 (RESP_PRESENT) +#define MMC_RESP_R4 (RESP_PRESENT) +#define MMC_RESP_R5 (RESP_PRESENT | RESP_CMDCODE | RESP_CRC) +#define MMC_RESP_R6 (RESP_PRESENT | RESP_CMDCODE | RESP_CRC) +#define MMC_RESP_R7 (RESP_PRESENT | RESP_CMDCODE | RESP_CRC) + +#define MMC_RESP_TYPE(cmd) ((cmd)->respType & (RESP_PRESENT | RESP_136 | RESP_CRC | RESP_BUSY | RESP_CMDCODE)) + +#define MMC_RESP_SPI_S1 (1 << 7) +#define MMC_RESP_SPI_S2 (1 << 8) +#define MMC_RESP_SPI_B4 (1 << 9) +#define MMC_RESP_SPI_BUSY (1 << 10) + +#define MMC_RESP_SPI_R1 (MMC_RESP_SPI_S1) +#define MMC_RESP_SPI_R1B (MMC_RESP_SPI_S1 | MMC_RESP_SPI_BUSY) +#define MMC_RESP_SPI_R2 (MMC_RESP_SPI_S1 | MMC_RESP_SPI_S2) +#define MMC_RESP_SPI_R3 (MMC_RESP_SPI_S1 | MMC_RESP_SPI_B4) +#define MMC_RESP_SPI_R4 (MMC_RESP_SPI_S1 | MMC_RESP_SPI_B4) +#define MMC_RESP_SPI_R5 (MMC_RESP_SPI_S1 | MMC_RESP_SPI_S2) +#define MMC_RESP_SPI_R7 (MMC_RESP_SPI_S1 | MMC_RESP_SPI_B4) + +enum MmcCsdStructure { + MMC_CSD_STRUCTURE_VER_1_0 = 0, + MMC_CSD_STRUCTURE_VER_1_1 = 1, + MMC_CSD_STRUCTURE_VER_1_2 = 2, /* Specification Version 4.1-4.2-4.3 */ + MMC_CSD_STRUCTURE_VER_OTHER = 3, /* Version is coded int the CSD_STRUCTURE byte in the EXT_CSD register. */ +}; + +enum MmcCsdSpecVersion { + MMC_CSD_SPEC_VER_0 = 0, + MMC_CSD_SPEC_VER_1 = 1, + MMC_CSD_SPEC_VER_2 = 2, + MMC_CSD_SPEC_VER_3 = 3, + MMC_CSD_SPEC_VER_4 = 4, +}; + +enum MmcCsdCardCmdClass { + MMC_CSD_CCC_BASIC = (1<<0), + MMC_CSD_CCC_BLOCK_READ = (1<<2), + MMC_CSD_CCC_BLOCK_WRITE = (1<<4), + MMC_CSD_CCC_ERASE = (1<<5), + MMC_CSD_CCC_WRITE_PROT = (1<<6), + MMC_CSD_CCC_LOCK_CARD = (1<<7), + MMC_CSD_CCC_APP_SPEC = (1<<8), + MMC_CSD_CCC_IO_MODE = (1<<9), + MMC_CSD_CCC_SWITCH = (1<<10), +}; + +enum MmcBusMode { + MMC_BUS_MODE_NULL = 0, + MMC_1_2V_DDR_MODE = 1, + MMC_1_8V_DDR_MODE = 2, + MMC_1_2V_SDR_MODE = 3, + MMC_1_8V_SDR_MODE = 4, +}; + +/* CID register define */ +struct MmcCid { + uint32_t mid; /* Manufacturer ID */ + char pnm[CID_PNM_LEN]; /* Product name */ + uint32_t psn; /* Product serial number */ + uint16_t oid; /* OEM/Application ID */ + uint16_t year; /* Manufacturing date: The y field */ + uint8_t month; /* Manufacturing date: The m field */ + /* + * The product revision is composed of two Binary Coded Decimal (BCD) digits, four bits each, + * representing an "n.m" revision number. + */ + uint8_t hwPrv; /* Product revision: n */ + uint8_t fwPrv; /* Product revision: m */ +}; + +/* CSD register define */ +struct MmcCsd { + uint8_t structure; /* CSD_STRUCTURE: [127:126] */ + uint8_t specVers; /* emmc-->SPEC_VERS: [125:122] */ + uint16_t ccc; /* card command classes: [95:84] */ + uint16_t taccClks; /* data read access-time-2 in CLK(NSAC)[111:104]: The unit for NSAC is 100 clock cycles. */ + uint32_t taccNs; /* data read access-time-1(TAAC)[119:112]: time unit[2:0] * time value[6:3] */ + uint32_t cSize; /* device size(C_SIZE): [73:62] */ + uint32_t r2wFactor; /* write speed factor(R2W_FACTOR): [28:26] */ + uint32_t maxDtr; /* max data transfer rate[103:96]: transfer rate unit[2:0] * time value[6:3] */ + uint32_t eraseSize; /* erase sector size: [45:39], emmc and sd are different. */ + uint32_t readBlkLen; /* max read data block length(READ_BL_LEN): [83:80] */ + uint32_t writeBlkLen; /* max write data block length(WRITE_BL_LEN): [25:22] */ + uint32_t capacity; /* see CSD Field C_SIZE. */ + uint32_t rdPartial : 1, /* partial blocks for read allowed: [79] */ + rdMisalign : 1, /* read block misalignment: [77] */ + wrPartial : 1, /* partial blocks for write allowed: [21] */ + wrMisalign : 1; /* write block misalignment: [78] */ +}; + +/* Emmc Extended CSD fields */ +enum EmmcExtendedCsdField { + EMMC_EXT_CSD_ENH_START_ADDR = 136, /* R/W, 4 bytes */ + EMMC_EXT_CSD_ENH_SIZE_MULT = 140, /* R/W, 3 bytes */ + EMMC_EXT_CSD_GP_SIZE_MULT = 143, /* R/W, 12 bytes */ + EMMC_EXT_CSD_PARTITIONS_ATTRIBUTE = 156, /* R/W */ + EMMC_EXT_CSD_PARTITIONING_SUPPORT = 160, /* RO */ + EMMC_EXT_CSD_HPI_MGMT = 161, /* R/W */ + EMMC_EXT_CSD_RST_N_FUNCTION = 162, /* R/W */ + EMMC_EXT_CSD_WR_REL_PARAM = 166, /* RO */ + EMMC_EXT_CSD_BOOT_WP = 173, /* R/W */ + EMMC_EXT_CSD_ERASE_GROUP_DEF = 175, /* R/W */ + EMMC_EXT_CSD_PARTITION_CONFIG = 179, /* R/W */ + EMMC_EXT_CSD_ERASED_MEM_CONT = 181, /* RO */ + EMMC_EXT_CSD_BUS_WIDTH = 183, /* R/W */ + EMMC_EXT_CSD_STROBE_SUPPORT = 184, /* RO */ + EMMC_EXT_CSD_HS_TIMING = 185, /* R/W */ + EMMC_EXT_CSD_POWER_CLASS = 187, /* R/W */ + EMMC_EXT_CSD_REV = 192, /* RO */ + EMMC_EXT_CSD_STRUCTURE = 194, /* RO */ + EMMC_EXT_CSD_CARD_TYPE = 196, /* RO */ + EMMC_EXT_CSD_OUT_OF_INTERRUPT_TIME = 198, /* RO */ + EMMC_EXT_CSD_PARTITION_SWITCH_TIME = 199, /* RO */ + EMMC_EXT_CSD_PWR_CL_52_195 = 200, /* RO */ + EMMC_EXT_CSD_PWR_CL_26_195 = 201, /* RO */ + EMMC_EXT_CSD_PWR_CL_52_360 = 202, /* RO */ + EMMC_EXT_CSD_PWR_CL_26_360 = 203, /* RO */ + EMMC_EXT_CSD_SEC_CNT = 212, /* RO, 4 bytes */ + EMMC_EXT_CSD_S_A_TIMEOUT = 217, /* RO */ + EMMC_EXT_CSD_HC_WP_GRP_SIZE = 221, /* RO */ + EMMC_EXT_CSD_REL_WR_SEC_C = 222, /* RO */ + EMMC_EXT_CSD_ERASE_TIMEOUT_MULT = 223, /* RO */ + EMMC_EXT_CSD_HC_ERASE_GRP_SIZE = 224, /* RO */ + EMMC_EXT_CSD_BOOT_MULTI = 226, /* RO */ + EMMC_EXT_CSD_SEC_TRIM_MULT = 229, /* RO */ + EMMC_EXT_CSD_SEC_ERASE_MULT = 230, /* RO */ + EMMC_EXT_CSD_SEC_FEATURE_SUPPORT = 231, /* RO */ + EMMC_EXT_CSD_TRIM_MULT = 232, /* RO */ + EMMC_EXT_CSD_PWR_CL_200_195 = 236, /* RO */ + EMMC_EXT_CSD_PWR_CL_200_360 = 237, /* RO */ + EMMC_EXT_CSD_PWR_CL_DDR_52_195 = 238, /* RO */ + EMMC_EXT_CSD_PWR_CL_DDR_52_360 = 239, /* RO */ + EMMC_EXT_CSD_HPI_FEATURES = 503, /* RO */ +}; + +#define EMMC_EXT_CSD_SEC_CNT_BYTES 4 +#define EMMC_EXT_CSD_ENH_START_ADDR_BYTES 4 +#define EMMC_EXT_CSD_GP_SIZE_MULT_BYTES 12 +#define EMMC_EXT_CSD_ENH_SIZE_MULT_BYTES 3 + +/* PARTITION_CONFIG[179], bit2-bit0: PARTITION_ACCESS. */ +#define EMMC_EXT_CSD_PART_CONFIG_ACCESS_MASK (0x7) + +enum EmmcExtCsdStructure { + EMMC_EXT_CSD_STRUCTURE_VER_1_0 = 0, + EMMC_EXT_CSD_STRUCTURE_VER_1_1 = 1, + EMMC_EXT_CSD_STRUCTURE_VER_1_2 = 2, /* Specification Version 4.1-4.2-4.3-4.4 */ + EMMC_EXT_CSD_STRUCTURE_VER_OTHER = 3, /* Reserved for future use. */ +}; + +enum EmmcExtCsdRev { + EMMC_EXT_CSD_REV_1_0 = 0, /* Revision 1.0(for MMC v4.0) */ + EMMC_EXT_CSD_REV_1_1 = 1, /* Revision 1.1(for MMC v4.1) */ + EMMC_EXT_CSD_REV_1_2 = 2, /* Revision 1.2(for MMC v4.2) */ + EMMC_EXT_CSD_REV_1_3 = 3, /* Revision 1.3(for MMC v4.3) */ + EMMC_EXT_CSD_REV_1_4 = 4, /* Revision 1.4(Obsolete) */ + EMMC_EXT_CSD_REV_1_5 = 5, /* Revision 1.5(for MMC v4.4.1) */ + EMMC_EXT_CSD_REV_OTHER = 6, /* Reserved */ +}; + +#define EMMC_EXT_CSD_CARD_TYPE_MASK 0x3F /* Mask out reserved bits */ + +enum EmmcExtCsdCardType { + EMMC_EXT_CSD_CARD_TYPE_26 = 0x01, /* Card can run at 26MHz */ + EMMC_EXT_CSD_CARD_TYPE_52 = 0x02, /* Card can run at 52MHz */ + EMMC_EXT_CSD_CARD_TYPE_DDR_1_8V = 0x04, /* DDR mode @1.8V or 3V I/O, Card can run at 52MHz */ + EMMC_EXT_CSD_CARD_TYPE_DDR_1_2V = 0x08, /* DDR mode @1.2V I/O, Card can run at 52MHz */ + EMMC_EXT_CSD_CARD_TYPE_DDR_52 = 0x0C, /* EMMC_EXT_CSD_CARD_TYPE_DDR_1_8V | EMMC_EXT_CSD_CARD_TYPE_DDR_1_2V */ + EMMC_EXT_CSD_CARD_TYPE_SDR_1_8V = 0x10, /* Card can run at 200MHz */ + EMMC_EXT_CSD_CARD_TYPE_SDR_1_8V_ALL = 0x13, + EMMC_EXT_CSD_CARD_TYPE_SDR_1_8V_ALL_DDR_1_8V = 0x17, + EMMC_EXT_CSD_CARD_TYPE_SDR_1_8V_ALL_DDR_1_2V = 0x1B, + EMMC_EXT_CSD_CARD_TYPE_SDR_1_8V_ALL_DDR_52 = 0x1F, + EMMC_EXT_CSD_CARD_TYPE_SDR_1_2V = 0x20, /* SDR mode @1.2V I/O, Card can run at 200MHz */ + EMMC_EXT_CSD_CARD_TYPE_SDR_1_2V_ALL = 0x23, + EMMC_EXT_CSD_CARD_TYPE_SDR_1_2V_ALL_DDR_1_8V = 0x27, + EMMC_EXT_CSD_CARD_TYPE_SDR_1_2V_ALL_DDR_1_2V = 0x2B, + EMMC_EXT_CSD_CARD_TYPE_SDR_1_2V_ALL_DDR_52 = 0x2F, + EMMC_EXT_CSD_CARD_TYPE_SDR_200 = 0x30, + EMMC_EXT_CSD_CARD_TYPE_SDR_ALL = 0x33, + EMMC_EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V = 0x37, + EMMC_EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V = 0x3B, + EMMC_EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52 = 0x3F, + EMMC_EXT_CSD_CARD_TYPE_HS400_1_8V = 0x40, /* Card can run at 200MHz DDR, 1.8V */ + EMMC_EXT_CSD_CARD_TYPE_HS400_1_2V = 0x80, /* Card can run at 200MHz DDR, 1.2V */ + EMMC_EXT_CSD_CARD_TYPE_HS400 = 0xC0, + EMMC_EXT_CSD_CARD_TYPE_HS400ES = 0x100, /* Card can run at HS400ES */ +}; + +enum EmmcExtCsdHighSpeedMaxDtr { + EMMC_EXT_CSD_HIGH_SPEED_26 = 26000000, /* 26M */ + EMMC_EXT_CSD_HIGH_SPEED_52 = 52000000, /* 52M */ + EMMC_EXT_CSD_HIGH_SPEED_200 = 200000000, /* 200M */ +}; + +/* High Priority Interrupt */ +enum EmmcExtCsdHpiFeatures { + EMMC_EXT_CSD_HPI_SUPPORT = (1 << 0), /* HPI mechanism supported flag. */ + EMMC_EXT_CSD_HPI_IMPLEMENTATION = (1 << 1), /* 0x0 : HPI mechanism implementation based on CMD13. + * 0x1 : HPI mechanism implementation based on CMD12. + */ +}; + +/* EXT_CSD access modes */ +enum EmmcExtCsdAccessMode { + EMMC_EXT_CSD_CMD_SET = 0x00, /* The command set is changed according to the Cmd Set field of the argument. */ + EMMC_EXT_CSD_SET_BITS = 0x01, /* + * The bits in the pointed byte are set, + * according to the '1' bits in the Value field. + */ + EMMC_EXT_CSD_CLEAR_BITS = 0x02, /* + * The bits in the pointed byte are cleared, + * according to the '1' bits in the Value field. + */ + EMMC_EXT_CSD_WRITE_BYTE = 0x03, /* The Value field is written into the pointed byte. */ +}; + +enum EmmcExtCsdBusWidth { + EMMC_EXT_CSD_BUS_WIDTH_1 = 0, /* 1 bit mode */ + EMMC_EXT_CSD_BUS_WIDTH_4 = 1, /* 4 bit mode */ + EMMC_EXT_CSD_BUS_WIDTH_8 = 2, /* 8 bit mode */ + EMMC_EXT_CSD_DDR_BUS_WIDTH_4 = 5, /* 4 bit DDR mode */ + EMMC_EXT_CSD_DDR_BUS_WIDTH_8 = 6, /* 8 bit DDR mode */ + EMMC_EXT_CSD_BUS_WIDTH_STROBE = (1 << 7), /* Enhanced strobe mode */ +}; + +enum EmmcExtCsdBusTiming { + EMMC_EXT_CSD_BUS_TIMING_HS = 1, /* High speed */ + EMMC_EXT_CSD_BUS_TIMING_HS200 = 2, /* HS200 */ + EMMC_EXT_CSD_BUS_TIMING_HS400 = 3, /* HS400 */ + EMMC_EXT_CSD_BUS_DRV_STR_SHIFT = 4, /* Driver Strength shift */ +}; + +enum EmmcExtCsdCmdSet { + EMMC_EXT_CSD_CMD_SET_NORMAL = (1 << 0), + EMMC_EXT_CSD_CMD_SET_SECURE = (1 << 1), + EMMC_EXT_CSD_CMD_SET_CPSECURE = (1 << 2), +}; + +/* + * PWR_CL_ff_vvv, PWR_CL_DDR_ff_vvv. + * Bits [7:4] code the current consumption for the 8 bit bus configuration. + * Bits [3:0] code the current consumption for the 4 bit bus configuration. + */ +#define EMMC_EXT_CSD_PWR_CL_8BIT_MASK 0xF0 /* 8 bit PWR CLS */ +#define EMMC_EXT_CSD_PWR_CL_4BIT_MASK 0x0F /* 8 bit PWR CLS */ +#define EMMC_EXT_CSD_PWR_CL_8BIT_SHIFT 4 +#define EMMC_EXT_CSD_PWR_CL_4BIT_SHIFT 0 + +/* + * S_A_TIMEOUT [217]. + * Max register value defined is 0x17 which equals 838.86ms timeout. Values between 0x18 and 0xFF are reserved. + */ +#define MAX_S_A_TIMEOUT_VALUE 0x17 + +/* + * PARTITIONING_SUPPORT [160]. + * Bit[7:2]: Reserved. + * Bit[1]: ENH_ATTRIBUTE_EN. + * 0x0: Device can not have enhanced technological features in partitions and user data area. + * 0x1: Device can have enhanced technological features in partitions and user data area. + * Bit[0]: PARTITIONING_EN. + * 0x0: Device does not support partitioning features. + * 0x1: Device supports partitioning features. + * Partitioning feature is optional for device. + */ +#define PARTITIONING_SUPPORT_ENH_ATTRIBUTE_EN (1 << 1) +#define PARTITIONING_SUPPORT_PARTITIONING_EN (1 << 0) + +/* + * PARTITIONS_ATTRIBUTE [156]. + * Bit[7:5]: Reserved. + * Bit[4]: ENH_4. 0x0: Default; 0x1: Set Enhanced attribute in General Purpose partition 4. + * Bit[3]: ENH_3. 0x0: Default; 0x1: Set Enhanced attribute in General Purpose partition 3. + * Bit[2]: ENH_2. 0x0: Default; 0x1: Set Enhanced attribute in General Purpose partition 2. + * Bit[1]: ENH_1. 0x0: Default; 0x1: Set Enhanced attribute in General Purpose partition 1. + * Bit[0]: ENH_USR. 0x0: Default; 0x1: Set Enhanced attribute in User Data Area. + */ +#define PARTITIONS_ATTRIBUTE_ENH_4 (1 << 4) +#define PARTITIONS_ATTRIBUTE_ENH_3 (1 << 3) +#define PARTITIONS_ATTRIBUTE_ENH_2 (1 << 2) +#define PARTITIONS_ATTRIBUTE_ENH_1 (1 << 1) +#define PARTITIONS_ATTRIBUTE_ENH_USR (1 << 0) + +/* + * The Extended CSD register defines the card properties and selected modes. It is 512 bytes long. The most + * significant 320 bytes are the Properties segment, which defines the card capabilities and cannot be modified + * by the host. The lower 192 bytes are the Modes segment, which defines the configuration the card is + * working in. These modes can be changed by the host by means of the SWITCH command. + */ +struct EmmcExtCsd { + uint8_t rev; /* EXT_CSD_REV: [192] */ + uint8_t eraseGroupDef; /* ERASE_GROUP_DEF: [175] */ + uint8_t secFeatureSupport; /* SEC_FEATURE_SUPPORT: [231] */ + uint8_t relWrSecorCount; /* Reliable write sector count(REL_WR_SEC_C): [222] */ + uint8_t wrRelParam; /* Write reliability parameter register(WR_REL_PARAM): [166] */ + uint8_t partConfig; /* PARTITION_CONFIG: [179] */ + uint32_t partSwitchTime; /* PARTITION_SWITCH_TIME:[199], ms */ + uint32_t saTimeout; /* Sleep/Awake Timeout = 100ns * 2^S_A_timeout, S_A_TIMEOUT: [217], Units: 100ns */ + uint32_t hsMaxDtr; /* high-speed max data transfer rate, according to cardType */ + uint32_t sectors; /* SEC_COUNT: [215:212], 512B/secter */ + uint32_t cardType; /* see rawCardType */ + uint32_t hcEraseSize; /* High-capacity erase unit size: [224] */ + uint32_t hcEraseTimeout; /* High-capacity erase timeout: [223], ms */ + uint32_t secTrimMult; /* Secure TRIM Multiplier: [229] */ + uint32_t secEraseMult; /* Secure Erase Multiplier: [230] */ + uint32_t trimTimeout; /* TRIM Multiplier: [232], TRIM Timeout = 300ms * TRIM_MULT */ + bool enhAreaEnable; /* enable bit */ + uint64_t enhAreaOffset; /* Enhanced User Data Start Address(ENH_START_ADDR): [139:136] */ + uint32_t enhAreaSize; /* Enhanced User Data Area Size(ENH_SIZE_MULT): [142:140] */ + uint32_t cache_size; /* Units: KB */ + bool hpiEnable; /* HPI enable bit */ + bool hpi; /* HPI_FEATURES: [503], Bit[0]: HPI_SUPPORT */ + uint32_t hpiCmd; /* HPI_FEATURES: [503], Bit[1]: HPI_IMPLEMENTATION, cmd used as HPI */ + uint32_t dataSectorSize; /* 512 bytes or 4KB */ + uint32_t data_tag_unit_size; /* DATA TAG UNIT size */ + uint32_t boot_ro_lock; /* ro lock support */ + uint32_t bootSize; /* Boot Partition size = 128Kbytes * BOOT_SIZE_MULT, BOOT_SIZE_MULT: [226] */ + uint8_t pwrClF52V195; /* Power class for 52MHz at 1.95V: [200] */ + uint8_t pwrClF26V195; /* Power class for 26MHz at 1.95V: [201] */ + uint8_t pwrClF52V360; /* Power class for 52MHz at 3.6V: [202] */ + uint8_t pwrClF26V360; /* Power class for 26MHz at 3.6V: [203] */ + uint8_t pwrClF200V195; /* Power class for 200MHz at 1.95V: [236] */ + uint8_t pwrClF200V360; /* Power class for 200MHz at 1.95V: [237] */ + uint8_t pwrClDdrF52V195; /* Power class for 52MHz, DDR at 3.6V: [238] */ + uint8_t pwrClDdrF52V360; /* Power class for 52MHz, DDR at 3.6V: [239] */ + uint8_t rawPartitionSupport; /* PARTITIONING_SUPPORT: [160] */ + uint8_t rawErasedMemCount; /* ERASED_MEM_CONT: [181] */ + uint8_t strobeSupport; /* strobe Support:[184] */ + uint8_t rawCsdStructure; /* CSD_STRUCTURE: [194] */ + uint8_t rawCardType; /* CARD_TYPE: [196] */ + uint8_t outOfInterruptTime; /* OUT_OF_INTERRUPT_TIME: [198], Units: 10ms */ + uint8_t rawSaTimeout; /* S_A_TIMEOUT: [217], 100ns */ + uint8_t rawHcWpGrpSize; /* High-capacity write protect group size(HC_WP_GRP_SIZE): [221] */ + uint8_t rawEraseTimeoutMult; /* ERASE_TIMEOUT_MULT: [223] */ + uint8_t rawHcEraseGrpSize; /* HC_ERASE_GRP_SIZE: [224] */ + uint8_t rawSecTrimMult; /* SEC_TRIM_MULT: [229] */ + uint8_t rawSecEraseMult; /* SEC_ERASE_MULT: [230] */ + uint8_t rawSecFeatureSupport; /* SEC_FEATURE_SUPPORT: [231] */ + uint8_t rawTrimMult; /* TRIM_MULT: [232] */ + uint8_t rawSectors[EMMC_EXT_CSD_SEC_CNT_BYTES]; /* SEC_COUNT: [215:212] */ +}; + +/* SD_SWITCH_FUNC mode */ +#define SD_SWITCH_FUNC_CHECK 0 +#define SD_SWITCH_FUNC_SET 1 + +/* SD_SWITCH_FUNC function groups */ +#define SD_SWITCH_FUNC_GRP_ACCESS 0 + +/* SD_SWITCH_FUNC access modes */ +#define SD_SWITCH_FUNC_ACCESS_DEF 0 +#define SD_SWITCH_FUNC_ACCESS_HS 1 + +/* + * As a response to the switch function command, the SD Memory Card will send R1 response on the CMD line, + * and 512 bits of status on the DAT lines. + */ +#define SD_SWITCH_FUNCTION_STATUS_BYTES_LEN 64 + +enum SdCmdCode { + SD_CMD_SEND_RELATIVE_ADDR = 3, /* ask the card to publish a new relative address (RCA). */ + SD_CMD_SWITCH_FUNC = 6, /* Checks switchable function (mode 0) and switchs card function (mode 1). */ + SD_CMD_SEND_IF_COND = 8, /* + * Sends SD Memory Card interface condition, which includes host supply voltage + * information and asks the card whether card supports voltage. + */ + SD_CMD_SWITCH_VOLTAGE = 11, /* Switch to 1.8V bus signaling level. */ + SD_CMD_SEND_TUNING_BLOCK = 19, /* 64 bytes tuning pattern is sent for SDR50 and SDR104. */ + SD_CMD_ERASE_WR_BLK_START = 32, /* sets the address of the first writeblock to be erased. */ + SD_CMD_ERASE_WR_BLK_END = 33, /* sets the address of the last write block of the continuous range to be erased. */ + SD_ACMD_SET_BUS_WIDTH = 6, /* + * Defines the data bus width ('00' =1bit or '10' =4 bits bus) to be used for data + * transfer. The allowed data bus widths are given in SCR register. + */ + SD_ACMD_SD_STATUS = 13, /* Send the SD Memory Card status. */ + SD_ACMD_SEND_NUM_WR_BLKS = 22, /* Send the number of the written (without errors) write blocks. */ + SD_ACMD_OP_COND = 41, /* + * Asks the accessed card to send its operating condition register(OCR) content + * in the response on the CMD line. + */ + SD_ACMD_SEND_SCR = 51, /* Reads the SD Configuration Register(SCR). */ +}; + +enum SdSwitchFuncMode { + SD_SWITCH_FUNC_MODE_CHECK = 0, /* + * Check function is used to query if the card supports + * a specific function or functions. + */ + SD_SWITCH_FUNC_MODE_SET = 1, /* Set function is uesd to switch the functionality of the card. */ +}; + +enum SdSwitchFuncGroup { + SD_SWITCH_FUNC_GROUP_1 = 0, /* Function Group 1 is defined as Bus Speed Mode switch. */ + SD_SWITCH_FUNC_GROUP_2 = 1, /* Function Group 2 is defined for Command System extension. */ + SD_SWITCH_FUNC_GROUP_3 = 2, /* Function Group 3 is defined as driver strength selection for UHS-I modes. */ + SD_SWITCH_FUNC_GROUP_4 = 3, /* Function Group 4 is defined as current limit switch for each UHS-I mode. */ + SD_SWITCH_FUNC_GROUP_5 = 4, /* reserved. */ + SD_SWITCH_FUNC_GROUP_6 = 5, /* reserved. */ +}; + +struct SdSwitchFuncParam { + uint32_t mode; + uint32_t group; + uint32_t value; +}; + +enum SdBusSpeedMode { + SD_BUS_SPEED_MODE_DS = 0, /* Default Speed up to 25MHz 3.3V signaling */ + SD_BUS_SPEED_MODE_UHS_SDR12 = 0, /* SDR up to 25MHz 1.8V signaling */ + SD_BUS_SPEED_MODE_HS = 1, /* High Speed 50MHz 3.3V signaling */ + SD_BUS_SPEED_MODE_UHS_SDR25 = 1, /* SDR up to 50MHz 1.8V signaling */ + SD_BUS_SPEED_MODE_UHS_SDR50 = 2, /* SDR up to 100MHz 1.8V signaling */ + SD_BUS_SPEED_MODE_UHS_SDR104 = 3, /* SDR up to 208MHz 1.8V signaling */ + SD_BUS_SPEED_MODE_UHS_DDR50 = 4, /* DDR up to 50MHz 1.8V signaling */ +}; + +/* sd max data transfer rate */ +enum SdMaxDtr { + SD_HIGH_SPEED_MAX_DTR = 50000000, + SD_UHS_SDR104_MAX_DTR = 208000000, + SD_UHS_SDR50_MAX_DTR = 100000000, + SD_UHS_DDR50_MAX_DTR = 50000000, + SD_UHS_SDR25_MAX_DTR = 50000000, + SD_UHS_SDR12_MAX_DTR = 25000000, +}; + +enum SdDrvType { + SD_DRV_TYPE_B = 0x01, + SD_DRV_TYPE_A = 0x02, + SD_DRV_TYPE_C = 0x04, + SD_DRV_TYPE_D = 0x08, +}; + +enum SdMaxCurrentLimitBit { + SD_MAX_CURRENT_LIMIT_200 = (1 << 0), /* 200mA bit */ + SD_MAX_CURRENT_LIMIT_400 = (1 << 1), /* 400mA bit */ + SD_MAX_CURRENT_LIMIT_600 = (1 << 2), /* 600mA bit */ + SD_MAX_CURRENT_LIMIT_800 = (1 << 3), /* 800mA bit */ +}; + +enum SdMaxCurrentLimitValue { + SD_MAX_CURRENT_LIMIT_200_VALUE = 0, /* 200mA */ + SD_MAX_CURRENT_LIMIT_400_VALUE = 1, /* 400mA */ + SD_MAX_CURRENT_LIMIT_600_VALUE = 2, /* 600mA */ + SD_MAX_CURRENT_LIMIT_800_VALUE = 3, /* 800mA */ +}; + +enum SdScrSpec { + SD_SCR_SPEC_0 = 0, + SD_SCR_SPEC_1 = 1, + SD_SCR_SPEC_2 = 2, +}; + +enum SdScrBusWidths { + SD_SCR_BUS_WIDTHS_1 = (1 << 0), + SD_SCR_BUS_WIDTHS_4 = (1 << 2), +}; + +#define SD_SCR_SPEED_CLASS_CONTROL_SUPPORT (0x1 << 0) /* cmd20 */ +#define SD_SCR_SET_BLOCK_COUNT_SUPPORT (0x1 << 1) /* cmd23 */ + +/* SD Configuration register */ +struct SdScr { + uint8_t sdSpec; + uint8_t sdSpec3; + uint8_t sdBusWidths; + uint8_t cmdSupport; +}; + +/* + * SPEED_CLASS Code Field, SEPPD_CLASS : VAL. + * 0 : 0, 1 : 2, 2 : 4, 3 : 6, 4 : 10, 5-FF : reversed. + */ +enum SdSsrSpeedClass { + SD_SSR_SPEED_CLASS_0 = 0, + SD_SSR_SPEED_CLASS_1 = 1, + SD_SSR_SPEED_CLASS_2 = 2, + SD_SSR_SPEED_CLASS_3 = 3, + SD_SSR_SPEED_CLASS_4 = 4, + SD_SSR_SPEED_CLASS_REV = 5, +}; + +enum SdSsrSpeedClassVal { + SD_SSR_SPEED_CLASS_0_VAL = 0, + SD_SSR_SPEED_CLASS_1_VAL = 2, + SD_SSR_SPEED_CLASS_2_VAL = 4, + SD_SSR_SPEED_CLASS_3_VAL = 6, + SD_SSR_SPEED_CLASS_4_VAL = 10, + SD_SSR_SPEED_CLASS_REV_VAL = 20, +}; + +enum SdSsrUhsSpeedGrade { + SD_SSR_UHS_SPEED_GRADE_0 = 0, /* Less than 10MB/sec */ + SD_SSR_UHS_SPEED_GRADE_1 = 1, /* 10MB/sec and above */ + SD_SSR_UHS_SPEED_GRADE_2 = 2, /* Reversed */ + SD_SSR_UHS_SPEED_GRADE_3 = 3, /* 30MB/sec and above */ + SD_SSR_UHS_SPEED_GRADE_4 = 4, /* 4h-Fh, Reversed */ +}; + +/* SD Status register */ +struct SdSsr { + uint8_t speedClass; + uint8_t auSize; + uint16_t eraseSize; + uint8_t eraseTimeout; + uint8_t eraseOffset; + uint8_t uhsSpeedGrade; + uint32_t auValue; +}; + +union SdSpec3BusMode { + uint32_t data; + struct dataBits { + uint32_t uhsSdr12 : 1; + uint32_t uhsSdr25 : 1; + uint32_t uhsSdr50 : 1; + uint32_t uhsSdr104 : 1; + uint32_t uhsDdr50 : 1; + + uint32_t reserved : 27; + } bits; +}; + +struct SdSwitchCaps { + enum SdMaxDtr hsMaxDtr; + enum SdMaxDtr uhsMaxDtr; + union SdSpec3BusMode sdSpec3BusMode; + enum SdDrvType sdSpec3DrvType; + enum SdMaxCurrentLimitBit sdSpec3CurrLimit; +}; + +enum SdioCmdCode { + /* + * It is similar to the operation of ACMD41 for SD memory cards. + * It is used to inquire about the valtage range needed by the I/O card. + */ + SDIO_SEND_OP_COND = 5, + /* + * It is the simplest means to access a single register within the total 128K of register space in any I/O function, + * including the common I/O area (CIA). This command reads or writes 1 byte using only 1 command/response pair. + * A common use is to initialize registers or monitor status values for I/O functions. This command is the fastest + * means to read or write single I/O registers, as it requires only a single command/response pair. + */ + SDIO_RW_DIRECT = 52, + /* + * This command allows the reading or writing of a large number of I/O registers with a single command. + * Since this is a data transfer command, it provides the highest possible transfer rate. + */ + SDIO_RW_EXTENDED = 53, +}; + +/* Card Common Control Registers (CCCR), Register Name--Address. */ +enum SdioCccrAddr { + CCCR_SDIO_REVISION = 0x00, /* bit3-bit0: CCCR_REVISION, bit7-bit4: SDIO_REVISION. */ + SD_SPECIFICATION_REVISION = 0x01, /* bit3-bit0: SD_REVISION, bit7-bit4: RFU. */ + IO_ENABLE = 0x02, /* bit7-bit1: IOEx, bit0: RFU. */ + IO_READY = 0x03, /* bit7-bit1: IORx, bit0: RFU. */ + INT_ENABLE = 0x04, /* bit7-bit1: IENx, bit0: IENM. */ + INT_PENDING = 0x05, /* bit7-bit1: INTx, bit0: RFU. */ + IO_ABORT = 0x06, /* bit2-bit0: ASx, bit3: RES, bit7-bit4: RFU. */ + BUS_INTERFACE_CONTROL = 0x07, /* + * bit1-bit0: Bus Width, bit2: S8B, bit3: RFU, bit4:RFU, bit5: ECSI, + * bit6: SCSI, bit7: CD Disable. + */ + CARD_CAPBILITY = 0x08, /* + * bit0: SDC, bit1: SMB, bit2: SRW, bit3: SBS, bit4: S4MI, bit5: E4MI, + * bit6: LSC, bit7: 4BLS. + */ + COMMON_CIS_POINTER = 0x09, /* 09h-0Bh, Pointer to card's common CIS. */ + BUS_SUSPEND = 0x0C, /* bit0: BS, bit1: BR, bit7-bit2: RFU. */ + FUNCTION_SELECT = 0x0D, /* bit3-bit0: FSx, bit6-bit4: RFU, bit7: DF. */ + EXEC_FLAG = 0x0E, /* bit7-bit0: EXx. */ + FN0_BLOCK_SIZE = 0x10, /* 11h-10h, I/O block size for Function 0. */ + POWER_CONTROL = 0x12, /* bit0: SMPC, bit1: EMPC, bit7-bit2: RFU. */ + BUS_SPEED_SELECT = 0x13, /* bit0: SHS, bit3-bit1: BSSx, bit7-bit4: RFU. */ + UHS_I_SUPPORT = 0x14, /* bit0: SSDR50, bit1: SSDR104, bit2: SDDR50, bit7-bit3: RFU. */ + DRIVER_STRENGTH = 0x15, /* bit0: SDTA, bit1: SDTC, bit2: SDTD, bit3: RFU, bit4: DTS0, bit5: DTS1, bit7-6: RFU. */ + INTERRUPT_EXTENSION = 0x16, /* bit0: SAI, bit1: EAI, bit7-bit2: RFU. */ +}; + +/* CCCR_SDIO_REVISION-->bit3-bit0: CCCR_REVISION. */ +enum SdioCccrRev { + SDIO_CCCR_VERSION_1_00 = 0x00, /* CCCR/FBR Version 1.00 */ + SDIO_CCCR_VERSION_1_10 = 0x01, /* CCCR/FBR Version 1.10 */ + SDIO_CCCR_VERSION_1_20 = 0x02, /* CCCR/FBR Version 1.20 */ + SDIO_CCCR_VERSION_3_00 = 0x03, /* CCCR/FBR Version 3.00 */ +}; + +/* CCCR_SDIO_REVISION-->bit7-bit4: SDIO_REVISION. */ +enum SdioCccrSdioRev { + SDIO_CCCR_SDIO_REV_1_00 = 0x00, /* SDIO Spec Version 1.00 */ + SDIO_CCCR_SDIO_REV_1_10 = 0x01, /* SDIO Spec Version 1.10 */ + SDIO_CCCR_SDIO_REV_1_20 = 0x02, /* SDIO Spec Version 1.20 */ + SDIO_CCCR_SDIO_REV_2_00 = 0x03, /* SDIO Spec Version 2.00 */ + SDIO_CCCR_SDIO_REV_3_00 = 0x04, /* SDIO Spec Version 3.00 */ +}; + +/* SD_SPECIFICATION_REVISION-->bit3-bit0: SD_REVISION. */ +enum SdioCccrSdRev { + SDIO_CCCR_SD_REV_1_01 = 0x00, /* SD Physical Spec Version 1.01 */ + SDIO_CCCR_SD_REV_1_10 = 0x01, /* SD Physical Spec Version 1.10 */ + SDIO_CCCR_SD_REV_2_00 = 0x02, /* SD Physical Spec Version 2.00 */ + SDIO_CCCR_SD_REV_3_0x = 0x03, /* SD Physical Spev Version 3.0x */ +}; + +/* IO_ABORT-->bit3: RES(I/O Card Reset). + * Setting the RES to 1 shall cause I/O functions perform a soft reset. This does not affect the current card + * protocol selection and CD Disable. It is auto cleared, so there is no need to rewrite a value of 0. + */ +#define SDIO_CCCR_RES 0x08 + +/* BUS_INTERFACE_CONTROL-->bit1-bit0: Bus Width. */ +enum SdioCccrWidth { + SDIO_CCCR_WIDTH_1BIT = 0x00, /* 1-bit */ + SDIO_CCCR_WIDTH_4BIT = 0x02, /* 4-bit bus */ + SDIO_CCCR_WIDTH_8BIT = 0x03 /* 8-bit bus(only for embedded SDIO) */ +}; + +/* BUS_INTERFACE_CONTROL-->bit5: ECSI. Enable Continuous SPI Interrupt. */ +#define SDIO_CCCR_ECSI 0x20 +/* BUS_INTERFACE_CONTROL-->bit6: SCSI. Support Continuous SPI Interrupt. */ +#define SDIO_CCCR_SCSI 0x40 +/* + * BUS_INTERFACE_CONTROL-->bit7: CD Disable. Card Detect Disable. + * Connect[0]/DisConnect[1] the 10K-90K ohm pull-up resistor on CD/DAT[3](pin1) of the card. + * The pull-up may be used for card detection. This bit shall be set to 1 before issuing CMD53. + */ +#define SDIO_CCCR_CD_DISABLE 0x80 + +/* CARD_CAPBILITY */ +enum SdioCccrCapbility { + SDIO_CCCR_CAP_SDC = 0x01, /* Support Direct Command(CMD52). If set, all functions shall accept and execute + * the CMD52 while data transfer is underway on the DAT[x] lines. + */ + SDIO_CCCR_CAP_SMB = 0x02, /* Support Multiple Block Transfer. If set, all functions shall accept and execute + * CMD53 with the optional block mode bit set. + */ + SDIO_CCCR_CAP_SRW = 0x04, /* Support Read Wait. If set, all functions on the card are able to accept + * the wait signal on DAT[2]. + */ + SDIO_CCCR_CAP_SBS = 0x08, /* Support Bus Control. If set, all functions except 0 shall accept a request to + * suspend operations and resume under host control. + */ + SDIO_CCCR_CAP_S4MI = 0x10, /* Support Block Gap Interrupt. Support bit of interrupt between blocks of data + * in 4-bit SD mode. If set, the SDIO card is able to signal an interrupt between + * blocks while data transfer is in progress. + */ + SDIO_CCCR_CAP_E4MI = 0x20, /* Enable Block Gap Interrupt. If set, the card shall generate interrupts + * during 4 bit multi-block data transfer. + */ + SDIO_CCCR_CAP_LSC = 0x40, /* Low-Speed Card. If set, it indicates that the SDIO card is a Low-Speed Card. + * if this bit is clear, The SDIO card is Full-Speed card. + */ + SDIO_CCCR_CAP_4BLS = 0x80, /* 4-bit Mode Support for Low-Speed Card. if the SDIO card is a Low-Speed Card and + * it supports 4-bit data transfer, then this bit shall be set. + */ +}; + +/* POWER_CONTROL-->bit0: SMPC, bit1: EMPC */ +enum SdioCccrPower { + SDIO_CCCR_POWER_SMPC = 0x01, /* Support Master Power Control. */ + SDIO_CCCR_POWER_EMPC = 0x02, /* Enable Master Power Control. */ +}; + +/* BUS_SPEED_SELECT-->bit0: SHS. Support High-Speed. */ +#define SDIO_CCCR_BUS_SPEED_SHS 0x01 +/* + * BUS_SPEED_SELECT-->BSS0. BSS0 = 0, Default Speed(25MHz); BSS0 = 1, High Speed(50MHz). + * If the card is initialized 3.3V signaling, then BSS0 is effective. When SHS is set to 0, + * writing to this bit is ignored and always indicates 0. The card operates in High-Speed timing mode + * with a clock rate up to 50MHz. + */ +#define SDIO_CCCR_BUS_SPEED_EHS 0x02 + +/* + * BUS_SPEED_SELECT-->bit3-bit1: BSSx. + * If the card is initialized 1.8V signaling, then BSS[2:0] is effective. A card that supports UHS-I shall + * support High Speed mode and SHS shall be set to 1. + */ +enum SdioCccrBusSpeed { + SDIO_CCCR_BUS_SPEED_SDR12 = 0, /* Max Clock Freq: 25MHz. */ + SDIO_CCCR_BUS_SPEED_SDR25 = 1, /* Max Clock Freq: 50MHz. */ + SDIO_CCCR_BUS_SPEED_SDR50 = 2, /* Max Clock Freq: 100MHz. */ + SDIO_CCCR_BUS_SPEED_SDR104 = 3, /* Max Clock Freq: 208MHz. */ + SDIO_CCCR_BUS_SPEED_DDR50 = 4, /* Max Clock Freq: 50MHz. */ +}; + +/* UHS_I_SUPPORT-->bit0: SSDR50, bit1: SSDR104, bit2: SDDR50. */ +enum SdioCccrUhsISupport { + SDIO_CCCR_UHS_I_SSDR50 = (1 << 0), /* Support SDR50. If this bit set to 1, SDR12 and SDR25 shall be supported. */ + SDIO_CCCR_UHS_I_SSDR104 = (1 << 1), /* + * Support SDR104. If this bit set to 1, + * SDR12, SDR25 and SDR50 shall be supported. + */ + SDIO_CCCR_UHS_I_SDDR50 = (1 << 2), /* + * Support DDR50. If this bit set to 1, + * SDR12, SDR25 and SDR50 shall be supported. + */ +}; + +/* DRIVER_STRENGTH-->bit0: SDTA, bit1: SDTC, bit2: SDTD, bit3: RFU, bit4: DTS0, bit5: DTS1, bit7-bit6: RFU. */ +enum SdioCccrDriveTypeSupport { + SDIO_CCCR_DRIVE_SDTA = (1 << 0), + SDIO_CCCR_DRIVE_SDTC = (1 << 1), + SDIO_CCCR_DRIVE_SDTD = (1 << 2), +}; + +/* DRIVER_STRENGTH-->bit4: DTS0, bit5: DTS1. */ +enum SdioCccrDriveTypeSelect { + SDIO_CCCR_DTS_TYPE_B = (0 << 4), + SDIO_CCCR_DTS_TYPE_A = (1 << 4), + SDIO_CCCR_DTS_YPE_C = (2 << 4), + SDIO_CCCR_DTS_TYPE_D = (3 << 4), +}; + +/* INTERRUPT_EXTENSION-->bit0: SAI, bit1: EAI. */ +#define SDIO_CCCR_SAI 0x01 /* Support Asynchronous Interrupt. */ +#define SDIO_CCCR_EAI 0x02 /* Enable Asynchronous Interrupt. */ + +/* Function Basic Registers (FBR), Register Name--Address. */ +enum SdioFbrAddr { + SDIO_FBR_STD_FUNCTION_INTERFACE_CODE = 0x00, /* + * bit7: CSA enable, bit6: support CSA, bit5-bit4L: RFU, + * bit3-bit0: Standard SDIO Function Interface Code. + */ + SDIO_FBR_EXT_STD_FUNCTION_INTERFACE_CODE = 0x01, /* Extended Standard SDIO Function Interface Code. */ + SDIO_FBR_POWER_SELECTION = 0x02, /* bit0: SPS, bit1: EPS, bit3-bit2: RFU, bit7-bit4: PSx. */ + SDIO_FBR_POINTER_CIS = 0x09, /* n09h-n0Bh: (Card Information Structure)CIS pointer */ + SDIO_FBR_POINTER_CSA = 0x0C, /* n0Ch-n0Eh: (Code Storage Area)CSA pointer */ + SDIO_FBR_CSA_DATA_ACCESS = 0x0F, /* Data access window to CSA. */ + SDIO_FBR_IO_BLOCK_SIZE = 0x10, /* I/O block size. */ +}; + +/* The address of FBR is from 00n00h to 00nFFh where n is the function number(1 to 7). */ +#define SDIO_FBR_BASE_ADDR(f) ((f) * 0x100) + +/* SDIO_FBR_STD_FUNCTION_INTERFACE_CODE-->bit3-bit0: Standard SDIO Function Interface Code. */ +enum SdioFbrStdFuncIfCode { + SDIO_FBR_NO_STD_IF = 0x00, /* No SDIO standard interface supported by this function. */ + SDIO_FBR_STD_UART = 0x01, /* This function support SDIO standard UART. */ + SDIO_FBR_STD_BLUETOOTH_TYPE_A = 0x02, /* This function support SDIO Bluetooth Type-A standard interface. */ + SDIO_FBR_STD_BLUETOOTH_TYPE_B = 0x03, /* This function support SDIO Bluetooth Type-B standard interface. */ + SDIO_FBR_STD_GPS = 0x04, /* This function support SDIO GPS standard interface. */ + SDIO_FBR_STD_CAMERA = 0x05, /* This function support SDIO Camera standard interface. */ + SDIO_FBR_STD_PHS = 0x06, /* This function support SDIO PHS standard interface. */ + SDIO_FBR_STD_WLAN = 0x07, /* This function support SDIO WLAN interface. */ + SDIO_FBR_STD_EMBEDDED_SDIO_ATA = 0x08, /* This function support Embedded SDIO-ATA standard interface. */ + SDIO_FBR_STD_BLUETOOTH_TYPE_A_AMP = 0x09, /* This function support SDIO Bluetooth Type-A AMP standard interface. */ + SDIO_FBR_STD_SDIO_IF = 0x0F, /* + * This function support an SDIO standard interface number greater than Eh. + * In this case, the value in SDIO_FBR_EXT_STD_FUNCTION_INTERFACE_CODE identifies + * the standard SDIO interfaces type. + */ +}; + +/* SDIO_FBR_STD_FUNCTION_INTERFACE_CODE-->bit6: support CSA. */ +#define SDIO_FBR_SUPPORTS_CSA 0x40 +/* + * SDIO_FBR_STD_FUNCTION_INTERFACE_CODE-->bit7: CSA enable. + * If this function does not support CSA, then this bit shall be R/O and always read as 0. + */ +#define SDIO_FBR_CSA_ENABLE 0x80 + +/* + * SDIO_FBR_POWER_SELECTION-->bit0: SPS(Support Power Selection). + * SPS = 0: This function has no Power Selection. EPS shall be zero. + * SPS = 1: This function has 2 Power modes which are selected by EPS. + * This bit is effective when EMPC = 1 in CCCR and PS[3:0] = 0. + */ +#define SDIO_FBR_POWER_SPS 0x01 +/* + * SDIO_FBR_POWER_SELECTION-->bit1: EPS(Enable Power Selection). + * Enable (low) Power Selection. + */ +#define SDIO_FBR_POWER_EPS 0x02 +/* Sdio function 1-7. */ +#define SDIO_MAX_FUNCTION_NUMBER 7 + +/* SDIO CMD5 response R4, [24]S18A(Switching to 1.8V Accepted). */ +#define SDIO_R4_S18A (1 << 24) +/* R4, [27]Memory Present. Set to 1 if the card also contains SD memory. Set to 0 if the card is I/O only. */ +#define SDIO_R4_MEMORY_PRESENT (1 << 27) + +/* R5: [15:8]Response flags, indicating the status of the SDIO card. */ +enum SdioR5CardStatusBits { + SDIO_R5_COM_CRC_ERROR = (1 << 15), /* The CRC chack of the previous command failed. */ + SDIO_R5_ILLEGAL_COMMAND = (1 << 14), /* Command not legal for the card State. */ + SDIO_R5_ERROR = (1 << 11), /* A general or an unknuwn error occurred during the operation. */ + SDIO_R5_FUNCTION_NUMBER = (1 << 9), /* An invalid function number was requested. */ + SDIO_R5_OUT_OF_RANGE = (1 << 8), /* The command's argument was out of the allowed range for this card. */ +}; + +/* R5: [13:12]IO_CURRENT_STATE. */ +enum SdioCurrentState { + SDIO_CURRENT_STATE_DIS = 0, /* Disable. Initialize, Standby and Inactive States(card not selected). */ + SDIO_CURRENT_STATE_CMD = 1, /* DAT lines free. Command waiting, Executing CMD52 in CMD State. */ + SDIO_CURRENT_STATE_TRN = 2, /* Transfer. Command executing with data transfer using DAT[0] or DAT[3:0] lines. */ +}; + +/* Card Common Control Registers(CCCR). */ +struct SdioCccr { + uint32_t sdioRev; + uint32_t sdRev; + uint32_t multiBlock : 1; + uint32_t lowSpeed : 1; + uint32_t lowSpeed4Bit : 1; + uint32_t highPower : 1; + uint32_t highSpeed : 1; + uint32_t disableCd : 1; +}; + +/* + * n09-n0B, these three bytes make up a 24-bit pointer(only the lower 17 bits are used) to the start of the + * Card Information Structure(CIS) that is associated with each function. + */ +#define SDIO_CCCR_CIS_START_ADDR_BYTES 3 + +/* + * There are 2 tuples with only a tuple code, the CISTPL_NULL and the CISTPL_END. These tuples do not have any + * additional bytes. For all other tuples, bytes 1 of each tuple contains a link to the next tuple in the chain. + * If the link field is 0, the the tuple body is empty. + * If the link contains FFh, the this tuple is the last tuple in its chain. + */ +enum SdioCisTupleCode { + SDIO_CIS_TPL_NULL = 0x00, /* Null tuple. */ + SDIO_CIS_TPL_CHECKSUM = 0x10, /* Checksum Control. */ + SDIO_CIS_TPL_VERS_1 = 0x15, /* Level 1 version/product-information. */ + SDIO_CIS_TPL_ALTSTR = 0x16, /* The Alternate Language String Tuple. */ + SDIO_CIS_TPL_MANFID = 0x20, /* Manufacturer Identification String Tuple. */ + SDIO_CIS_TPL_FUNCID = 0x21, /* Function Identification Tuple. */ + SDIO_CIS_TPL_FUNCE = 0x22, /* Function Extensions. */ + SDIO_CIS_TPL_SDIO_STD = 0x91, /* Additional information for functions built to support application + * specifications for standard SDIO functions. + */ + SDIO_CIS_TPL_SDIO_EXT = 0x92, /* Reserved for future use with SDIO devices. */ + SDIO_CIS_TPL_END = 0xFF, /* The End-0f-chain Tuple. */ +}; + +#define SDIO_CIS_TPL_MANFID_MIN_SIZE 0x04 +#define SDIO_CIS_TPL_FUNCE_COMMON_MIN_SIZE 0x04 +#define SDIO_CIS_TPL_FUNCE_FUNCTION_PC_MIN_SIZE 0x1C +#define SDIO_CIS_TPL_FUNCE_FUNCTION_PC_MAX_SIZE 0x2A +#define SDIO_CIS_TPLFE_ENABLE_TIMEOUT_VAL_DEF 100 + +enum SdioCisTupleFunceType { + SDIO_CIS_TPL_FUNCE_COMMON = 0, /* This tuple gives the host common information about the card. */ + SDIO_CIS_TPL_FUNCE_FUNCTION_PC = 1, /* Extended Data 01h is defined for Power Control. */ + SDIO_CIS_TPL_FUNCE_FUNCTION_PS = 2, /* Extended of this tuple indicates that the card supports the Power State. */ +}; + +/* Card Information Structure(CIS). */ +struct SdioCis { + uint16_t vendorId; + uint16_t deviceId; + uint16_t blkSize; + uint32_t maxDtr; +}; + +/* + * The Card Information Structure is one or more chains(or linked lists) of data blocks or tuples. + * Basic Tuple Format: TPL_CODE, TPL_LINK, The tuple body. + */ +struct SdioCisTuple { + uint8_t tplCode; /* Tuple code: CISTPL_XXX */ + uint8_t tplLink; /* TPL_LINK Offset to next tuple in chains. This is the number of bytes in the tuple body. */ + uint8_t tplBody[0]; /* The tuple body(n bytes). */ +}; + +struct SdioCmdParam { + uint32_t funcNum; + uint32_t regAddr; + uint8_t writeData; + bool incrAddrFlag; + bool writeflag; + bool scatterFlag; + uint32_t scatterLen; +}; + +struct SdioRwBlockInfo { + uint32_t addr; + uint8_t *buf; + uint32_t size; + uint32_t scatterLen; + bool writeFlag; + bool incrAddrFlag; + bool scatterFlag; +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* _MMC_PROTOCOL_H */ diff --git a/support/platform/include/mmc/mmc_sd.h b/support/platform/include/mmc/mmc_sd.h new file mode 100644 index 00000000..451566cc --- /dev/null +++ b/support/platform/include/mmc/mmc_sd.h @@ -0,0 +1,40 @@ +/* + * 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 MMC_SD_H +#define MMC_SD_H + +#include "mmc_corex.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +struct SdRegister { + uint32_t rawScr[SCR_LEN]; + uint16_t rawDsr; + struct SdScr scr; + struct SdSsr ssr; + struct SdSwitchCaps swCaps; +}; + +struct SdDevice { + struct MmcDevice mmc; + enum SdBusSpeedMode busSpeedMode; + struct SdRegister reg; +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* MMC_SD_H */ diff --git a/support/platform/include/mmc/mmc_sdio.h b/support/platform/include/mmc/mmc_sdio.h new file mode 100644 index 00000000..9ee57952 --- /dev/null +++ b/support/platform/include/mmc/mmc_sdio.h @@ -0,0 +1,106 @@ +/* + * 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 MMC_SDIO_H +#define MMC_SDIO_H + +#include "mmc_sd.h" +#include "osal_thread.h" +#include "sdio_if.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +struct SdioFunction { + struct SdioDevice *dev; + uint32_t maxBlkSize; + uint32_t curBlkSize; + uint32_t funcNum; + uint8_t funcClass; + uint16_t vendorId; + uint16_t deviceId; + uint32_t timeOut; + SdioIrqHandler *irqHandler; +}; + +struct SdioRegister { + struct SdioCccr cccr; + struct SdioCis cis; +}; + +struct SdioDevice { + struct SdDevice sd; + struct SdioDeviceOps *sdioOps; + struct SdioRegister sdioReg; + uint32_t functions; + struct SdioFunction *sdioFunc[SDIO_MAX_FUNCTION_NUMBER]; + struct SdioFunction *curFunction; + struct OsalThread thread; /* irq thread */ + struct OsalSem sem; + bool irqPending; + bool threadRunning; +}; + +struct SdioDeviceOps { + int32_t (*incrAddrReadBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t); + int32_t (*incrAddrWriteBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t); + int32_t (*fixedAddrReadBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t, uint32_t); + int32_t (*fixedAddrWriteBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t, uint32_t); + int32_t (*func0ReadBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t); + int32_t (*func0WriteBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t); + int32_t (*setBlockSize)(struct SdioDevice *, uint32_t); + int32_t (*getCommonInfo)(struct SdioDevice *, SdioCommonInfo *, uint32_t); + int32_t (*setCommonInfo)(struct SdioDevice *, SdioCommonInfo *, uint32_t); + int32_t (*flushData)(struct SdioDevice *); + int32_t (*enableFunc)(struct SdioDevice *); + int32_t (*disableFunc)(struct SdioDevice *); + int32_t (*claimIrq)(struct SdioDevice *, SdioIrqHandler *); + int32_t (*releaseIrq)(struct SdioDevice *); + int32_t (*findFunc)(struct SdioDevice *, struct SdioFunctionConfig *); + int32_t (*claimHost)(struct SdioDevice *); + int32_t (*releaseHost)(struct SdioDevice *); +}; + +int32_t SdioDeviceFindFunction(struct SdioDevice *sdio, struct SdioFunctionConfig *config); +int32_t SdioDeviceIncrAddrReadBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size); +int32_t SdioDeviceIncrAddrWriteBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size); +int32_t SdioDeviceFixedAddrReadBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); +int32_t SdioDeviceFixedAddrWriteBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); +int32_t SdioDeviceFunc0ReadBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size); +int32_t SdioDeviceFunc0WriteBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size); +int32_t SdioDeviceSetBlockSize(struct SdioDevice *sdio, uint32_t blockSize); +int32_t SdioDeviceGetCommonInfo(struct SdioDevice *sdio, + SdioCommonInfo *info, SdioCommonInfoType infoType); +int32_t SdioDeviceSetCommonInfo(struct SdioDevice *sdio, + SdioCommonInfo *info, SdioCommonInfoType infoType); +int32_t SdioDeviceFlushData(struct SdioDevice *sdio); +int32_t SdioDeviceClaimHost(struct SdioDevice *sdio); +int32_t SdioDeviceReleaseHost(struct SdioDevice *sdio); +int32_t SdioDeviceEnableFunc(struct SdioDevice *sdio); +int32_t SdioDeviceDisableFunc(struct SdioDevice *sdio); +int32_t SdioDeviceClaimIrq(struct SdioDevice *sdio, SdioIrqHandler *irqHandler); +int32_t SdioDeviceReleaseIrq(struct SdioDevice *sdio); + +void SdioDeviceAddOps(struct SdioDevice *sdio, void *ops); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* MMC_SDIO_H */ diff --git a/support/platform/src/common/platform_common.c b/support/platform/src/common/platform_common.c new file mode 100644 index 00000000..694bda31 --- /dev/null +++ b/support/platform/src/common/platform_common.c @@ -0,0 +1,196 @@ +/* + * 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_log.h" +#include "osal_spinlock.h" +#include "platform_common.h" + +static struct PlatformModuleInfo g_platformModules[] = { +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO) || defined(CONFIG_DRIVERS_HDF_PLATFORM_GPIO) + { + .moduleType = PLATFORM_MODULE_GPIO, + .moduleName = "PLATFORM_MODULE_GPIO", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2C) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I2C) + { + .moduleType = PLATFORM_MODULE_I2C, + .moduleName = "PLATFORM_MODULE_I2C", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_SPI) || defined(CONFIG_DRIVERS_HDF_PLATFORM_SPI) + { + .moduleType = PLATFORM_MODULE_SPI, + .moduleName = "PLATFORM_MODULE_SPI", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PIN) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PIN) + { + .moduleType = PLATFORM_MODULE_PIN, + .moduleName = "PLATFORM_MODULE_PIN", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_CLOCK) || defined(CONFIG_DRIVERS_HDF_PLATFORM_CLOCK) + { + .moduleType = PLATFORM_MODULE_CLOCK, + .moduleName = "PLATFORM_MODULE_CLOCK", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_REGULATOR) || defined(CONFIG_DRIVERS_HDF_PLATFORM_REGULATOR) + { + .moduleType = PLATFORM_MODULE_REGULATOR, + .moduleName = "PLATFORM_MODULE_REGULATOR", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_MIPI_DSI) || defined(CONFIG_DRIVERS_HDF_PLATFORM_MIPI_DSI) + { + .moduleType = PLATFORM_MODULE_MIPI_DSI, + .moduleName = "PLATFORM_MODULE_MIPI_DSI", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_UART) || defined(CONFIG_DRIVERS_HDF_PLATFORM_UART) + { + .moduleType = PLATFORM_MODULE_UART, + .moduleName = "PLATFORM_MODULE_UART", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_SDIO) || defined(CONFIG_DRIVERS_HDF_PLATFORM_SDIO) + { + .moduleType = PLATFORM_MODULE_SDIO, + .moduleName = "PLATFORM_MODULE_SDIO", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_MDIO) || defined(CONFIG_DRIVERS_HDF_PLATFORM_MDIO) + { + .moduleType = PLATFORM_MODULE_MDIO, + .moduleName = "PLATFORM_MODULE_MDIO", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_APB) || defined(CONFIG_DRIVERS_HDF_PLATFORM_APB) + { + .moduleType = PLATFORM_MODULE_APB, + .moduleName = "PLATFORM_MODULE_APB", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PCIE) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PCIE) + { + .moduleType = PLATFORM_MODULE_PCIE, + .moduleName = "PLATFORM_MODULE_PCIE", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PCM) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PCM) + { + .moduleType = PLATFORM_MODULE_PCM, + .moduleName = "PLATFORM_MODULE_PCM", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2S) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I2S) + { + .moduleType = PLATFORM_MODULE_I2S, + .moduleName = "PLATFORM_MODULE_I2S", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PWM) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PWM) + { + .moduleType = PLATFORM_MODULE_PWM, + .moduleName = "PLATFORM_MODULE_PWM", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_DMA) || defined(CONFIG_DRIVERS_HDF_PLATFORM_DMA) + { + .moduleType = PLATFORM_MODULE_DMA, + .moduleName = "PLATFORM_MODULE_DMA", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_ADC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_ADC) + { + .moduleType = PLATFORM_MODULE_ADC, + .moduleName = "PLATFORM_MODULE_ADC", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_RTC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_RTC) + { + .moduleType = PLATFORM_MODULE_RTC, + .moduleName = "PLATFORM_MODULE_RTC", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_WDT) || defined(CONFIG_DRIVERS_HDF_PLATFORM_WDT) + { + .moduleType = PLATFORM_MODULE_WDT, + .moduleName = "PLATFORM_MODULE_WDT", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_I3C) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I3C) + { + .moduleType = PLATFORM_MODULE_I3C, + .moduleName = "PLATFORM_MODULE_I3C", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_CAN) || defined(CONFIG_DRIVERS_HDF_PLATFORM_CAN) + { + .moduleType = PLATFORM_MODULE_CAN, + .moduleName = "PLATFORM_MODULE_CAN", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_HDMI) || defined(CONFIG_DRIVERS_HDF_PLATFORM_HDMI) + { + .moduleType = PLATFORM_MODULE_HDMI, + .moduleName = "PLATFORM_MODULE_HDMI", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_MMC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_MMC) + { + .moduleType = PLATFORM_MODULE_MMC, + .moduleName = "PLATFORM_MODULE_MMC", + }, +#endif +#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_MTD) || defined(CONFIG_DRIVERS_HDF_PLATFORM_MTD) + { + .moduleType = PLATFORM_MODULE_MTD, + .moduleName = "PLATFORM_MODULE_MTD", + }, +#endif + { + .moduleType = PLATFORM_MODULE_DEFAULT, + .moduleName = "PLATFORM_MODULE_DEFAULT", + }, +}; + +static OsalSpinlock g_platformSpin; +static bool g_platformReady; + +void PlatformGlobalLock(void) +{ + if (g_platformReady == false) { + (void)OsalSpinInit(&g_platformSpin); + g_platformReady = true; + } + (void)OsalSpinLock(&g_platformSpin); +} + +void PlatformGlobalUnlock(void) +{ + (void)OsalSpinUnlock(&g_platformSpin); +} + +struct PlatformModuleInfo *PlatformModuleInfoGet(enum PlatformModuleType moduleType) +{ + int32_t i; + + for (i = 0; i < PlatformModuleInfoCount(); i++) { + if (g_platformModules[i].moduleType == moduleType) { + return &g_platformModules[i]; + } + } + return NULL; +} + +int32_t PlatformModuleInfoCount(void) +{ + return sizeof(g_platformModules) / sizeof(g_platformModules[0]); +} diff --git a/support/platform/src/common/platform_device.c b/support/platform/src/common/platform_device.c new file mode 100644 index 00000000..91d5a0a9 --- /dev/null +++ b/support/platform/src/common/platform_device.c @@ -0,0 +1,217 @@ +/* + * 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_log.h" +#include "osal_mem.h" +#include "platform_common.h" +#include "platform_device.h" +#include "platform_manager.h" + +#define PLATFORM_DEV_NAME_DEFAULT "platform_device" + +static void PlatformDeviceOnFirstGet(struct HdfSRef *sref) +{ + (void)sref; +} + +static void PlatformDeviceOnLastPut(struct HdfSRef *sref) +{ + struct PlatformDevice *device = NULL; + struct PlatformNotifierNode *pos = NULL; + struct PlatformNotifierNode *tmp = NULL; + + if (sref == NULL) { + return; + } + + device = CONTAINER_OF(sref, struct PlatformDevice, ref); + if (device == NULL) { + HDF_LOGE("PlatformDeviceOnLastPut: get device is NULL!"); + return; + } + (void)OsalSpinLock(&device->spin); + device->ready = false; + + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &device->notifiers, struct PlatformNotifierNode, node) { + if (pos != NULL && pos->notifier != NULL && pos->notifier->handle != NULL) { + pos->notifier->handle(device, PLAT_EVENT_DEAD, pos->notifier->data); + } + } + + (void)OsalSpinUnlock(&device->spin); +} + +struct IHdfSRefListener g_platObjListener = { + .OnFirstAcquire = PlatformDeviceOnFirstGet, + .OnLastRelease = PlatformDeviceOnLastPut, +}; + +static void PlatformEventHandle(struct PlatformDevice *device, enum PlatformEventType event, void *data) +{ + if (device == NULL) { + return; + } + if (event == PLAT_EVENT_DEAD) { + (void)OsalSemPost(&device->released); + } +} + +static struct PlatformNotifier g_platformEventNotifier = { + .data = NULL, + .handle = PlatformEventHandle, +}; + +void PlatformDeviceInit(struct PlatformDevice *device) +{ + if (device == NULL) { + HDF_LOGW("PlatformDeviceInit: device is NULL"); + return; + } + + if (device->name == NULL) { + device->name = PLATFORM_DEV_NAME_DEFAULT; + } + + (void)OsalSpinInit(&device->spin); + (void)OsalSemInit(&device->released, 0); + DListHeadInit(&device->node); + DListHeadInit(&device->notifiers); + HdfSRefConstruct(&device->ref, &g_platObjListener); + + if (PlatformDeviceRegNotifier(device, &g_platformEventNotifier) != HDF_SUCCESS) { + HDF_LOGE("PlatformDeviceInit: reg notifier fail"); + } + device->ready = true; +} + +void PlatformDeviceUninit(struct PlatformDevice *device) +{ + if (device == NULL) { + HDF_LOGW("PlatformDevice: device is NULL"); + return; + } + device->ready = false; + + /* make sure no reference anymore before exit. */ + (void)OsalSemWait(&device->released, HDF_WAIT_FOREVER); + PlatformDeviceClearNotifier(device); + (void)OsalSemDestroy(&device->released); + (void)OsalSpinDestroy(&device->spin); +} + +struct PlatformDevice *PlatformDeviceGet(struct PlatformDevice *device) +{ + if (device == NULL) { + HDF_LOGE("PlatformDeviceGet: device is NULL"); + return NULL; + } + + HdfSRefAcquire(&device->ref); + return device; +} + +void PlatformDevicePut(struct PlatformDevice *device) +{ + if (device != NULL) { + HdfSRefRelease(&device->ref); + } +} + +int32_t PlatformDeviceRegNotifier(struct PlatformDevice *device, struct PlatformNotifier *notifier) +{ + struct PlatformNotifierNode *pNode = NULL; + + if (device == NULL || notifier == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + pNode = (struct PlatformNotifierNode *)OsalMemCalloc(sizeof(*pNode)); + if (pNode == NULL) { + HDF_LOGE("PlatformDeviceRegNotifier: alloc pNode fail"); + return HDF_ERR_MALLOC_FAIL; + } + pNode->notifier = notifier; + (void)OsalSpinLock(&device->spin); + DListInsertTail(&pNode->node, &device->notifiers); + (void)OsalSpinUnlock(&device->spin); + return HDF_SUCCESS; +} + +static void PlatformDeviceRemoveNotifier(struct PlatformDevice *device, struct PlatformNotifier *notifier) +{ + struct PlatformNotifierNode *pos = NULL; + struct PlatformNotifierNode *tmp = NULL; + + if (device->notifiers.next == NULL || device->notifiers.prev == NULL) { + HDF_LOGD("PlatformDeviceRemoveNotifier: notifiers not init."); + return; + } + + (void)OsalSpinLock(&device->spin); + DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &device->notifiers, struct PlatformNotifierNode, node) { + if (pos != NULL && pos->notifier != NULL) { + /* if notifier not set, we remove all the notifier nodes. */ + if (notifier == NULL || notifier == pos->notifier) { + DListRemove(&pos->node); + OsalMemFree(pos); + } + if (notifier == pos->notifier) { + break; + } + } + } + (void)OsalSpinUnlock(&device->spin); +} + + +void PlatformDeviceUnregNotifier(struct PlatformDevice *device, struct PlatformNotifier *notifier) +{ + if (device == NULL || notifier == NULL) { + return; + } + PlatformDeviceRemoveNotifier(device, notifier); +} + +void PlatformDeviceClearNotifier(struct PlatformDevice *device) +{ + if (device == NULL) { + return; + } + PlatformDeviceRemoveNotifier(device, NULL); +} + +int32_t PlatformDeviceAdd(struct PlatformDevice *device) +{ + struct PlatformManager *manager = NULL; + + if (device == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + PlatformDeviceInit(device); + manager = device->manager; + if (manager == NULL) { + manager = PlatformManagerGet(PLATFORM_MODULE_DEFAULT); + } + return PlatformManagerAddDevice(manager, device); +} + +void PlatformDeviceDel(struct PlatformDevice *device) +{ + struct PlatformManager *manager = NULL; + + if (device == NULL) { + return; + } + + manager = device->manager; + if (manager == NULL) { + manager = PlatformManagerGet(PLATFORM_MODULE_DEFAULT); + } + PlatformManagerDelDevice(manager, device); + PlatformDeviceUninit(device); +} diff --git a/support/platform/src/common/platform_manager.c b/support/platform/src/common/platform_manager.c new file mode 100644 index 00000000..0f3ccf66 --- /dev/null +++ b/support/platform/src/common/platform_manager.c @@ -0,0 +1,155 @@ +/* + * 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_log.h" +#include "osal_mem.h" +#include "osal_sem.h" +#include "platform_common.h" +#include "platform_device.h" +#include "platform_manager.h" + +#define PLATFORM_MANAGER_NAME_DEFAULT "PlatformManagerDefault" + +static void PlatformManagerInit(struct PlatformManager *manager) +{ + if (manager->name == NULL) { + manager->name = PLATFORM_MANAGER_NAME_DEFAULT; + } + + OsalSpinInit(&manager->spin); + DListHeadInit(&manager->devices); +} + +struct PlatformManager *PlatformManagerCreate(const char *name) +{ + struct PlatformManager *manager = NULL; + + manager = (struct PlatformManager *)OsalMemCalloc(sizeof(*manager)); + if (manager == NULL) { + HDF_LOGE("PlatformManagerCreate: malloc fail!"); + return NULL; + } + manager->name = name; + PlatformManagerInit(manager); + return manager; +} + +struct PlatformManager *PlatformManagerGet(enum PlatformModuleType module) +{ + struct PlatformManager *manager = NULL; + struct PlatformModuleInfo *info = NULL; + + info = PlatformModuleInfoGet(module); + if (info == NULL) { + HDF_LOGE("PlatformManagerGet: get module(%d) info failed", module); + return NULL; + } + + PlatformGlobalLock(); + if (info->priv == NULL) { + manager = PlatformManagerCreate(info->moduleName); + info->priv = manager; + } else { + manager = (struct PlatformManager *)info->priv; + } + PlatformGlobalUnlock(); + + return manager; +} + +int32_t PlatformManagerAddDevice(struct PlatformManager *manager, struct PlatformDevice *device) +{ + struct PlatformDevice *tmp = NULL; + bool repeatId = false; + + if (manager == NULL || device == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + device->manager = manager; + + if (PlatformDeviceGet(device) == NULL) { // keep a reference by manager + return HDF_PLT_ERR_DEV_GET; + } + + (void)OsalSpinLock(&manager->spin); + DLIST_FOR_EACH_ENTRY(tmp, &manager->devices, struct PlatformDevice, node) { + if (tmp != NULL && tmp->magic == device->magic) { + repeatId = true; + HDF_LOGE("PlatformManagerAddDevice: repeated magic:%u!", device->magic); + break; + } + } + if (!repeatId) { + DListInsertTail(&device->node, &manager->devices); + } + (void)OsalSpinUnlock(&manager->spin); + + if (repeatId) { + PlatformDevicePut(device); + } + return repeatId ? HDF_PLT_ERR_ID_REPEAT : HDF_SUCCESS; +} + +void PlatformManagerDelDevice(struct PlatformManager *manager, struct PlatformDevice *device) +{ + if (manager == NULL || device == NULL) { + return; + } + + if (device->manager != manager) { + HDF_LOGE("PlatformManagerDelDevice: manager mismatch!"); + return; + } + + (void)OsalSpinLock(&manager->spin); + if (!DListIsEmpty(&device->node)) { + DListRemove(&device->node); + } + (void)OsalSpinUnlock(&manager->spin); + PlatformDevicePut(device); // put the reference hold by manager +} + +struct PlatformDevice *PlatformManagerFindDevice(struct PlatformManager *manager, void *data, + bool (*match)(struct PlatformDevice *pdevice, void *data)) +{ + struct PlatformDevice *tmp = NULL; + struct PlatformDevice *pdevice = NULL; + + if (manager == NULL || match == NULL) { + return NULL; + } + if (manager->devices.prev == NULL || manager->devices.next == NULL) { + HDF_LOGD("PlatformManagerFindDevice: devices not init."); + return NULL; + } + + (void)OsalSpinLock(&manager->spin); + DLIST_FOR_EACH_ENTRY(tmp, &manager->devices, struct PlatformDevice, node) { + if (tmp != NULL && match(tmp, data)) { + pdevice = PlatformDeviceGet(tmp); + } + } + (void)OsalSpinUnlock(&manager->spin); + + return pdevice; +} + +static bool PlatformDeviceMatchByMagic(struct PlatformDevice *device, void *data) +{ + uint32_t magic = (uint32_t)(uintptr_t)data; + + return (device != NULL && device->magic == magic); +} + +struct PlatformDevice *PlatformManagerGetDeviceByMagic(struct PlatformManager *manager, uint32_t magic) +{ + if (manager == NULL) { + return NULL; + } + return PlatformManagerFindDevice(manager, (void *)(uintptr_t)magic, PlatformDeviceMatchByMagic); +} diff --git a/support/platform/src/common/platform_queue.c b/support/platform/src/common/platform_queue.c new file mode 100644 index 00000000..3a83ee01 --- /dev/null +++ b/support/platform/src/common/platform_queue.c @@ -0,0 +1,157 @@ +/* + * 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 "platform_queue.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "osal_mutex.h" +#include "osal_thread.h" + +#define MMC_QUEUE_THREAD_STAK 20000 + +static int32_t PlatformQueueThreadWorker(void *data) +{ + int32_t ret; + struct PlatformQueue *queue = (struct PlatformQueue *)data; + struct PlatformMsg *msg = NULL; + + while (true) { + /* wait envent */ + ret = OsalSemWait(&queue->sem, HDF_WAIT_FOREVER); + if (ret != HDF_SUCCESS) { + continue; + } + + (void)OsalSpinLock(&queue->spin); + if (DListIsEmpty(&queue->msgs)) { + msg = NULL; + } else { + msg = DLIST_FIRST_ENTRY(&queue->msgs, struct PlatformMsg, node); + DListRemove(&msg->node); + } + (void)OsalSpinUnlock(&queue->spin); + /* message process */ + if (msg != NULL) { + (void)(queue->handle(queue, msg)); + if (msg->block == true) { + (void)OsalSemPost(&msg->sem); + } + } + } + return HDF_SUCCESS; +} + +struct PlatformQueue *PlatformQueueCreate(PlatformMsgHandle handle, const char *name, void *data) +{ + int32_t ret; + struct PlatformQueue *queue = NULL; + + if (handle == NULL) { + return NULL; + } + + queue = (struct PlatformQueue *)OsalMemCalloc(sizeof(*queue)); + if (queue == NULL) { + HDF_LOGE("PlatformQueueCreate: alloc queue fail!"); + return NULL; + } + (void)OsalSpinInit(&queue->spin); + (void)OsalSemInit(&queue->sem, 0); + DListHeadInit(&queue->msgs); + + ret = OsalThreadCreate(&queue->thread, (OsalThreadEntry)PlatformQueueThreadWorker, (void *)queue); + if (ret != HDF_SUCCESS) { + HDF_LOGE("PlatformQueueCreate: create thread fail!"); + OsalMemFree(queue); + return NULL; + } + + queue->name = (name == NULL) ? "PlatformWorkerThread" : name; + queue->handle = handle; + queue->data = data; + return queue; +} + +void PlatformQueueDestroy(struct PlatformQueue *queue) +{ + if (queue == NULL) { + return; + } + + (void)OsalThreadDestroy(&queue->thread); + (void)OsalSemDestroy(&queue->sem); + (void)OsalSpinDestroy(&queue->spin); + OsalMemFree(queue); +} + +int32_t PlatformQueueStart(struct PlatformQueue *queue) +{ + int32_t ret; + struct OsalThreadParam cfg; + + if (queue == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + cfg.name = (char *)queue->name; + cfg.priority = OSAL_THREAD_PRI_HIGHEST; + cfg.stackSize = MMC_QUEUE_THREAD_STAK; + ret = OsalThreadStart(&queue->thread, &cfg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("PlatformQueueStart: start thread fail:%d", ret); + return ret; + } + + return HDF_SUCCESS; +} + +int32_t PlatformQueueSuspend(struct PlatformQueue *queue) +{ + if (queue == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + return OsalThreadSuspend(&queue->thread); +} + +int32_t PlatformQueueResume(struct PlatformQueue *queue) +{ + if (queue == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + return OsalThreadResume(&queue->thread); +} + +void PlatformQueueAddMsg(struct PlatformQueue *queue, struct PlatformMsg *msg) +{ + if (queue == NULL || msg == NULL) { + return; + } + + if (msg->block == true) { + (void)OsalSemInit(&msg->sem, 0); + } + DListHeadInit(&msg->node); + msg->error = HDF_SUCCESS; + (void)OsalSpinLock(&queue->spin); + DListInsertTail(&msg->node, &queue->msgs); + (void)OsalSpinUnlock(&queue->spin); + /* notify the worker thread */ + (void)OsalSemPost(&queue->sem); +} + +int32_t PlatformMsgWait(struct PlatformMsg *msg) +{ + if (msg == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + if (msg->block == false) { + return HDF_SUCCESS; + } + return OsalSemWait(&msg->sem, HDF_WAIT_FOREVER); +} diff --git a/support/platform/src/mmc/emmc_if.c b/support/platform/src/mmc/emmc_if.c new file mode 100644 index 00000000..b3c9f206 --- /dev/null +++ b/support/platform/src/mmc/emmc_if.c @@ -0,0 +1,159 @@ +/* + * 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 __USER__ +#include "devsvc_manager_clnt.h" +#include "mmc_emmc.h" +#endif +#include "emmc_if.h" +#include "hdf_base.h" +#ifdef __USER__ +#include "hdf_io_service_if.h" +#endif +#include "hdf_log.h" +#include "osal_mem.h" +#include "securec.h" + +#define HDF_LOG_TAG emmc_if_c + +#ifdef __USER__ +static int32_t EmmcGetCidReadReplyData(struct HdfSBuf *reply, uint8_t *cid, uint32_t size) +{ + uint32_t rLen; + const void *rBuf = NULL; + + if (HdfSbufReadBuffer(reply, &rBuf, &rLen) == false) { + HDF_LOGE("EmmcGetCidReadReplyData: read rBuf fail!"); + return HDF_ERR_IO; + } + if (size != rLen) { + HDF_LOGE("EmmcGetCidReadReplyData: err len:%u, rLen:%u", size, rLen); + if (rLen > size) { + rLen = size; + } + } + + if (memcpy_s(cid, size, rBuf, rLen) != EOK) { + HDF_LOGE("EmmcGetCidReadReplyData: memcpy rBuf fail!"); + return HDF_ERR_IO; + } + return HDF_SUCCESS; +} + +int32_t EmmcServiceGetCid(struct HdfIoService *service, uint8_t *cid, uint32_t size) +{ + int32_t ret; + struct HdfSBuf *reply = NULL; + + reply = HdfSBufObtainDefaultSize(); + if (reply == NULL) { + HDF_LOGE("EmmcServiceGetCid: failed to obtain reply!"); + ret = HDF_ERR_MALLOC_FAIL; + goto __EXIT; + } + + if (service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) { + HDF_LOGE("EmmcServiceGetCid: dispatcher or Dispatch is NULL!"); + ret = HDF_ERR_NOT_SUPPORT; + goto __EXIT; + } + + ret = service->dispatcher->Dispatch(&service->object, EMMC_CMD_GET_CID, NULL, reply); + if (ret != HDF_SUCCESS) { + HDF_LOGE("EmmcServiceGetCid: failed to send service call:%d", ret); + goto __EXIT; + } + + ret = EmmcGetCidReadReplyData(reply, cid, size); + if (ret != HDF_SUCCESS) { + goto __EXIT; + } + HDF_LOGD("EmmcServiceGetCid: success"); + +__EXIT: + if (reply != NULL) { + HdfSBufRecycle(reply); + } + return ret; +} + +#else +static int32_t EmmcDeviceGetFromHandle(DevHandle handle, struct EmmcDevice **emmc) +{ + struct MmcDevice *mmc = NULL; + + if (handle == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + if (emmc == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + mmc = MmcCntlrGetDevice((struct MmcCntlr *)handle); + if (mmc == NULL) { + return HDF_PLT_ERR_NO_DEV; + } + if (mmc->type != MMC_DEV_EMMC) { + MmcDevicePut(mmc); + return HDF_PLT_ERR_DEV_TYPE; + } + + *emmc = (struct EmmcDevice *)mmc; + return HDF_SUCCESS; +} + +#endif + +int32_t EmmcGetCid(DevHandle handle, uint8_t *cid, uint32_t size) +{ + if (handle == NULL) { + HDF_LOGE("EmmcGetCid: handle is NULL!"); + return HDF_ERR_INVALID_OBJECT; + } + + if (cid == NULL || size < EMMC_CID_LEN) { + HDF_LOGE("EmmcGetCid: error parms!"); + return HDF_ERR_INVALID_PARAM; + } +#ifdef __USER__ + return EmmcServiceGetCid((struct HdfIoService *)handle, cid, size); +#else + struct EmmcDevice *emmc = NULL; + int32_t ret; + + if (EmmcDeviceGetFromHandle(handle, &emmc) != HDF_SUCCESS) { + return HDF_ERR_INVALID_OBJECT; + } + ret = EmmcDeviceGetCid(emmc, cid, size); + MmcDevicePut((struct MmcDevice *)emmc); + return ret; +#endif +} + +void EmmcGetHuid(uint8_t *cid, uint32_t size) +{ + DevHandle handle = NULL; + if (cid == NULL || size == 0) { + HDF_LOGE("EmmcGetUdid: error parms!"); + return; + } + if (memset_s(cid, sizeof(uint8_t) * size, 0, sizeof(uint8_t) * size) != EOK) { + HDF_LOGE("EmmcGetUdid: memset_s fail!"); + return; + } + handle = EmmcOpen(0); + if (handle == NULL) { + HDF_LOGD("EmmcGetUdid: open fail, use default value!"); + return; + } + if (EmmcGetCid(handle, cid, size) != HDF_SUCCESS) { + HDF_LOGD("EmmcGetUdid: get fail, use default value!"); + } + EmmcClose(handle); +} diff --git a/support/platform/src/mmc/mmc_block.c b/support/platform/src/mmc/mmc_block.c new file mode 100644 index 00000000..2917a284 --- /dev/null +++ b/support/platform/src/mmc/mmc_block.c @@ -0,0 +1,166 @@ +/* + * 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 "storage_block.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "mmc_corex.h" +#include "mmc_sd.h" +#include "osal_mem.h" +#include "securec.h" + +static ssize_t MmcBlockRead(struct StorageBlock *sb, uint8_t *buf, size_t secStart, size_t nSec) +{ + if (sb == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (sb->type == MEDIA_MMC) { + return MmcDeviceRead((struct MmcDevice *)sb->media, buf, secStart, nSec); + } + return HDF_ERR_NOT_SUPPORT; +} + +static ssize_t MmcBlockWrite(struct StorageBlock *sb, const uint8_t *buf, size_t secStart, size_t nSec) +{ + if (sb == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (sb->type == MEDIA_MMC) { + return MmcDeviceWrite((struct MmcDevice *)sb->media, (uint8_t *)buf, secStart, nSec); + } + return HDF_ERR_NOT_SUPPORT; +} + +static ssize_t MmcBlockErase(struct StorageBlock *sb, size_t secStart, size_t nSec) +{ + if (sb == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (sb->type == MEDIA_MMC) { + return MmcDeviceErase((struct MmcDevice *)sb->media, secStart, nSec); + } + return HDF_ERR_NOT_SUPPORT; +} + +static uint32_t MmcBlockGetAuSize(struct StorageBlock *sb) +{ + struct MmcDevice *mmc = NULL; + struct SdDevice *sd = NULL; + + if (sb == NULL || sb->media == NULL) { + HDF_LOGE("MmcBlockGetAuSize: invalid sb or media!"); + return 0; + } + + if (sb->type != MEDIA_MMC) { + HDF_LOGE("MmcBlockGetAuSize: media is not mmc!"); + return 0; + } + + mmc = (struct MmcDevice *)sb->media; + if (mmc->type != MMC_DEV_SD) { + HDF_LOGE("MmcBlockGetAuSize: media is not sd!"); + return 0; + } + sd = (struct SdDevice *)mmc; + + return sd->reg.ssr.auSize; +} + +static bool MmcBlockIsPresent(struct StorageBlock *sb) +{ + return (sb != NULL && sb->type == MEDIA_MMC && + MmcDeviceIsPresent((struct MmcDevice *)sb->media)); +} + +static struct StorageBlockMethod g_mmcBlockOps = { + .read = MmcBlockRead, + .write = MmcBlockWrite, + .erase = MmcBlockErase, + .getAuSize = MmcBlockGetAuSize, + .isPresent = MmcBlockIsPresent, +}; + +static int32_t MmcBlockInit(struct StorageBlock *sb, struct MmcDevice *mmc) +{ + int32_t ret; + size_t nameSize; + + if (PlatformDeviceGet(&mmc->device) == NULL) { + return HDF_PLT_ERR_DEV_GET; + } + mmc->sb = sb; + sb->type = MEDIA_MMC; + sb->media = mmc; + sb->secSize = mmc->secSize; + sb->capacity = mmc->capacity; + sb->removeable = (mmc->state.bits.removeable == 0) ? false : true; + sb->ops = &g_mmcBlockOps; + nameSize = sizeof(sb->name); + ret = snprintf_s(sb->name, nameSize, nameSize - 1, "/dev/mmcblk%0d", mmc->cntlr->index); + if (ret <= 0) { + PlatformDevicePut(&mmc->device); + } + + return HDF_SUCCESS; +} + +static void MmcBlockUninit(struct StorageBlock *sb) +{ + struct MmcDevice *mmc = (struct MmcDevice *)sb->media; + + mmc->sb = NULL; + PlatformDevicePut(&mmc->device); +} + +int32_t MmcBlockAdd(struct MmcDevice *mmc) +{ + int32_t ret; + struct StorageBlock *sb = NULL; + + if (mmc == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + sb = (struct StorageBlock *)OsalMemCalloc(sizeof(*sb)); + if (sb == NULL) { + return HDF_ERR_MALLOC_FAIL; + } + + ret = MmcBlockInit(sb, mmc); + if (ret != HDF_SUCCESS) { + OsalMemFree(sb); + return ret; + } + + ret = StorageBlockAdd(sb); + if (ret != HDF_SUCCESS) { + MmcBlockUninit(sb); + OsalMemFree(sb); + return ret; + } + + return HDF_SUCCESS; +} + +void MmcBlockDel(struct MmcDevice *mmc) +{ + struct StorageBlock *sb = NULL; + + if (mmc == NULL) { + return; + } + sb = mmc->sb; + if (sb == NULL) { + return; + } + + StorageBlockDel(sb); + MmcBlockUninit(sb); + OsalMemFree(sb); +} diff --git a/support/platform/src/mmc/mmc_core.c b/support/platform/src/mmc/mmc_core.c new file mode 100644 index 00000000..6d2670b1 --- /dev/null +++ b/support/platform/src/mmc/mmc_core.c @@ -0,0 +1,1195 @@ + /* + * 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 "device_resource_if.h" +#include "hdf_dlist.h" +#include "hdf_log.h" +#include "mmc_block.h" +#include "mmc_corex.h" +#include "mmc_dispatch.h" +#include "mmc_emmc.h" +#include "mmc_sdio.h" +#include "osal_mem.h" +#include "osal_time.h" + +#define HDF_LOG_TAG mmc_core_c + +#define MMC_POWER_ON_DELAY_TIME 10 /* 10ms */ +#define MMC_OCR_MAX_VOLTAGE_BIT 23 +#define MMC_OCR_MAX_SHIFT_BITS 3 +#define MMC_DETECET_RETRY 5 +#define MMC_REQUEST_RETRY 3 +#define MMC_MAX_SECTOR_NUM 2048 +#define MMC_MAX_ERASE_SECTOR 0x100000 /* 512M */ +#define SDIO_IRQ_TASK_STACK_SIZE 0x2000 + +int32_t MmcCntlrDoRequest(struct MmcCntlr *cntlr, struct MmcCmd *cmd) +{ + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (cmd == NULL) { + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->ops == NULL || cntlr->ops->request == NULL) { + return HDF_ERR_NOT_SUPPORT; + } + return cntlr->ops->request(cntlr, cmd); +} + +static int32_t MmcCntlrExecRequest(struct MmcCntlr *cntlr, struct MmcCmd *cmd) +{ + uint32_t i; + int32_t ret; + + for (i = 0; i < MMC_REQUEST_RETRY; i++) { + MmcCntlrLock(cntlr); + ret = MmcCntlrDoRequest(cntlr, cmd); + MmcCntlrUnlock(cntlr); + if (ret != HDF_SUCCESS) { + continue; + } + if (cmd->returnError != HDF_SUCCESS) { + continue; + } + if (cmd->data != NULL && cmd->data->returnError != HDF_SUCCESS) { + continue; + } + break; + } + return ret; +} + +static int32_t MmcCntlrPlug(struct MmcCntlr *cntlr) +{ + uint32_t i; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (MmcCntlrDevPluged(cntlr) != true) { + HDF_LOGD("MmcCntlrPlug: dev is not plugged!"); + return HDF_SUCCESS; + } + + /* dev not delete. */ + if (cntlr->curDev != NULL) { + MmcCntlrLock(cntlr); + MmcDeleteDev(cntlr); + MmcCntlrUnlock(cntlr); + } + + if (cntlr->ops != NULL && cntlr->ops->systemInit != NULL) { + if (cntlr->ops->systemInit(cntlr) != HDF_SUCCESS) { + HDF_LOGE("MmcCntlrPlug: system init fail!"); + return HDF_FAILURE; + } + } + + MmcCntlrLock(cntlr); + for (i = 0; i < MMC_DETECET_RETRY; i++) { + cntlr->detecting = true; + if (MmcDoDetect(cntlr) == HDF_SUCCESS) { + MmcDeviceAddOps(cntlr->curDev, NULL); + cntlr->detecting = false; + MmcCntlrUnlock(cntlr); + return HDF_SUCCESS; + } + } + cntlr->detecting = false; + MmcCntlrUnlock(cntlr); + + return HDF_FAILURE; +} + +static int32_t MmcCntlrUnplug(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL) { + HDF_LOGE("MmcCntlrUnplug: cntlr is null!"); + return HDF_ERR_INVALID_OBJECT; + } + + MmcCntlrLock(cntlr); + MmcDeleteDev(cntlr); + MmcCntlrUnlock(cntlr); + HDF_LOGD("host%d: a dev is removed!", cntlr->index); + return HDF_SUCCESS; +} + +static int32_t MmcCntlrSdioRescanHandle(struct MmcCntlr *cntlr) +{ + uint8_t val; + int32_t error; + + if (cntlr == NULL) { + HDF_LOGE("MmcCntlrSdioRescanHandle: cntlr is null."); + return HDF_ERR_INVALID_OBJECT; + } + + if (cntlr->curDev != NULL && cntlr->curDev->state.bits.present > 0) { + if (cntlr->curDev->type == MMC_DEV_SDIO || cntlr->curDev->type == MMC_DEV_COMBO) { + error = SdioReadCccrIoEnable(cntlr, &val); + if (error != HDF_SUCCESS) { + HDF_LOGD("re-detect sdio."); + MmcCntlrPlug(cntlr); + } else { + HDF_LOGD("sdio no need to rescan."); + return HDF_SUCCESS; + } + } else { + HDF_LOGD("sd/emmc rescan does not support."); + } + } else { + HDF_LOGD("init detect fail, re-detect sdio."); + MmcCntlrPlug(cntlr); + } + + if (cntlr->curDev == NULL) { + HDF_LOGE("sdio rescan fail, please reset card!"); + return HDF_ERR_DEVICE_BUSY; + } + return HDF_SUCCESS; +} + +static int32_t MmcMsgHandleDefault(struct PlatformQueue *queue, struct PlatformMsg *msg) +{ + int32_t ret; + struct MmcCntlr *cntlr = NULL; + struct MmcMsg *mmcMsg = NULL; + + if (queue == NULL || msg == NULL) { + HDF_LOGE("MmcMsgHandleDefault: msg or queue is null!"); + return HDF_ERR_INVALID_OBJECT; + } + + cntlr = (struct MmcCntlr *)queue->data; + if (cntlr == NULL) { + HDF_LOGE("MmcMsgHandleDefault: cntlr is null!"); + return HDF_ERR_INVALID_OBJECT; + } + mmcMsg = (struct MmcMsg *)msg; + switch (msg->code) { + case MMC_MSG_PLUG: + ret = MmcCntlrPlug(cntlr); + break; + case MMC_MSG_UNPLUG: + ret = MmcCntlrUnplug(cntlr); + break; + case MMC_MSG_REQUEST: + ret = MmcCntlrExecRequest(cntlr, mmcMsg->mmcCmd); + break; + case MMC_MSG_SDIO_RESCAN: + ret = MmcCntlrSdioRescanHandle(cntlr); + break; + default: + ret = HDF_ERR_NOT_SUPPORT; + break; + } + + if (mmcMsg->msg.block == false) { + OsalMemFree(mmcMsg); + } + return ret; +} + +static int32_t MmcCntlrInit(struct MmcCntlr *cntlr) +{ + int32_t ret; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + if (cntlr->index >= MMC_CNTLR_NR_MAX) { + HDF_LOGE("MmcCntlrInit: invalid cntlr index:%u", cntlr->index); + return HDF_ERR_INVALID_PARAM; + } + + if (cntlr->hdfDevObj == NULL) { + HDF_LOGE("MmcCntlrInit: no HdfDeviceObject attached!"); + return HDF_ERR_INVALID_OBJECT; + } + + ret = OsalMutexInit(&cntlr->mutex); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcCntlrInit: mutex init fail!"); + return ret; + } + + cntlr->msgQueue = PlatformQueueCreate(MmcMsgHandleDefault, NULL, cntlr); + if (cntlr->msgQueue == NULL) { + HDF_LOGE("MmcCntlrInit: failed to create msg queue!"); + return HDF_PLT_ERR_OS_API; + } + ret = PlatformQueueStart(cntlr->msgQueue); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcCntlrInit: failed to start msg queue!"); + PlatformQueueDestroy(cntlr->msgQueue); + return ret; + } + + cntlr->service.Dispatch = MmcIoDispatch; + cntlr->hdfDevObj->service = &(cntlr->service); + cntlr->device.magic = cntlr->index; + cntlr->device.hdfDev = cntlr->hdfDevObj; + return HDF_SUCCESS; +} + +static void MmcCntlrUninit(struct MmcCntlr *cntlr) +{ + if (cntlr != NULL) { + (void)OsalMutexDestroy(&cntlr->mutex); + PlatformQueueDestroy(cntlr->msgQueue); + } +} + +int32_t MmcCntlrAdd(struct MmcCntlr *cntlr) +{ + int32_t ret; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + ret = MmcCntlrInit(cntlr); + if (ret != HDF_SUCCESS) { + return ret; + } + + cntlr->device.manager = PlatformManagerGet(PLATFORM_MODULE_MMC); + ret = PlatformDeviceAdd(&cntlr->device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcCntlrAdd: device add fail!"); + MmcCntlrUninit(cntlr); + return ret; + } + return HDF_SUCCESS; +} + +void MmcCntlrRemove(struct MmcCntlr *cntlr) +{ + if (cntlr != NULL) { + MmcCntlrUninit(cntlr); + PlatformDeviceDel(&cntlr->device); + } +} + +void MmcCntlrSetDevice(struct MmcCntlr *cntlr, struct MmcDevice *mmc) +{ + if (cntlr == NULL || mmc == NULL) { + return; + } + cntlr->curDev = mmc; +} + +struct MmcDevice *MmcCntlrGetDevice(struct MmcCntlr *cntlr) +{ + struct MmcDevice *mmc = NULL; + + if (cntlr != NULL) { + mmc = cntlr->curDev; + } + return MmcDeviceGet(mmc); +} + +static int32_t MmcCntlrPostMsg(struct MmcCntlr *cntlr, struct MmcMsg *mmcMsg) +{ + int32_t ret; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (mmcMsg == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + PlatformQueueAddMsg(cntlr->msgQueue, &mmcMsg->msg); + ret = PlatformMsgWait(&mmcMsg->msg); + if (mmcMsg->msg.block == true) { + (void)OsalSemDestroy(&mmcMsg->msg.sem); + OsalMemFree(mmcMsg); + } + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcCntlrPostMsg: wait mmc msg fail!"); + return ret; + } + return HDF_SUCCESS; +} + +void MmcCntlrSetClock(struct MmcCntlr *cntlr, uint32_t clock) +{ + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->setClock == NULL) { + return; + } + cntlr->curDev->workPara.clock = clock; + cntlr->ops->setClock(cntlr, clock); +} + +void MmcCntlrSetBusWidth(struct MmcCntlr *cntlr, enum MmcBusWidth width) +{ + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->setBusWidth == NULL) { + return; + } + cntlr->curDev->workPara.width = width; + cntlr->ops->setBusWidth(cntlr, width); +} + +void MmcCntlrSetBusTiming(struct MmcCntlr *cntlr, enum MmcBusTiming timing) +{ + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->setBusTiming == NULL) { + return; + } + cntlr->curDev->workPara.timing = timing; + cntlr->ops->setBusTiming(cntlr, timing); +} + +void MmcCntlrSetEnhanceSrobe(struct MmcCntlr *cntlr, bool enable) +{ + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->setEnhanceSrobe == NULL) { + return; + } + cntlr->ops->setEnhanceSrobe(cntlr, enable); +} + +int32_t MmcCntlrSwitchVoltage(struct MmcCntlr *cntlr, enum MmcVolt voltage) +{ + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->switchVoltage == NULL) { + return HDF_ERR_INVALID_PARAM; + } + return cntlr->ops->switchVoltage(cntlr, voltage); +} + +bool MmcCntlrDevReadOnly(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->devReadOnly == NULL) { + return false; + } + return cntlr->ops->devReadOnly(cntlr); +} + +bool MmcCntlrDevPluged(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->devPluged == NULL) { + return false; + } + + if (cntlr->caps.bits.nonremovable > 0) { + return true; + } + return cntlr->ops->devPluged(cntlr); +} + +bool MmcCntlrDevBusy(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->devBusy == NULL) { + return true; + } + + return cntlr->ops->devBusy(cntlr); +} + +int32_t MmcCntlrTune(struct MmcCntlr *cntlr, uint32_t cmdCode) +{ + if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->tune == NULL) { + return HDF_ERR_INVALID_PARAM; + } + return cntlr->ops->tune(cntlr, cmdCode); +} + +void MmcCntlrSelectWorkVoltage(struct MmcCntlr *cntlr, union MmcOcr *ocr) +{ + uint32_t tmpOcr; + uint32_t i; + + /* ignore reveserd. */ + if ((ocr->ocrData & 0x7F) > 0) { + ocr->ocrData &= (~0x7F); + } + /* use low voltage shuould both host and dev support. */ + if (cntlr->ocrDef.bits.vdd1v65To1v95 == 0) { + ocr->bits.vdd1v65To1v95 = 0; + } + + /* + * Based on the voltage range supported by the host and the voltage range read from the OCR register, + * obtain the voltage range supported by both the host and the OCR register, + * and then select the minimum voltage value. + */ + tmpOcr = ((ocr->ocrData) & (cntlr->ocrDef.ocrData)); + for (i = 0; i <= MMC_OCR_MAX_VOLTAGE_BIT; i++) { + if ((tmpOcr & (1 << i)) > 0) { + break; + } + } + + if (i > 0 && i <= MMC_OCR_MAX_VOLTAGE_BIT) { + tmpOcr &= (MMC_OCR_MAX_SHIFT_BITS << i); + cntlr->vddBit = i; + } else { + tmpOcr = 0; + } + cntlr->curDev->reg.ocr.ocrData = tmpOcr; +} + +void MmcCntlrPowerUp(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL || cntlr->ops == NULL) { + return; + } + + if (cntlr->ops->setEnhanceSrobe != NULL) { + cntlr->ops->setEnhanceSrobe(cntlr, false); + } + /* disable clock. */ + if (cntlr->ops->setClock != NULL) { + cntlr->ops->setClock(cntlr, 0); + } + /* power up. */ + if (cntlr->ops->setPowerMode != NULL) { + cntlr->ops->setPowerMode(cntlr, MMC_POWER_MODE_POWER_UP); + } + if (cntlr->ops->setBusWidth != NULL) { + cntlr->ops->setBusWidth(cntlr, BUS_WIDTH1); + } + if (cntlr->ops->setBusTiming != NULL) { + cntlr->ops->setBusTiming(cntlr, BUS_TIMING_MMC_DS); + } + OsalMDelay(MMC_POWER_ON_DELAY_TIME); + + /* enable clock. */ + if (cntlr->ops->setClock != NULL) { + cntlr->ops->setClock(cntlr, cntlr->freqDef); + } + /* power on. */ + if (cntlr->ops->setPowerMode != NULL) { + cntlr->ops->setPowerMode(cntlr, MMC_POWER_MODE_POWER_ON); + } + OsalMDelay(MMC_POWER_ON_DELAY_TIME); + + if (cntlr->ops->hardwareReset != NULL && cntlr->caps.bits.hardwareReset > 0) { + cntlr->ops->hardwareReset(cntlr); + } + /* init voltage 3.3v. */ + if (cntlr->ops->switchVoltage != NULL) { + cntlr->ops->switchVoltage(cntlr, cntlr->voltDef); + } +} + +void MmcCntlrPowerOff(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL || cntlr->ops == NULL) { + return; + } + + /* disable clock. */ + if (cntlr->ops->setClock != NULL) { + cntlr->ops->setClock(cntlr, 0); + } + /* power up. */ + if (cntlr->ops->setPowerMode != NULL) { + cntlr->ops->setPowerMode(cntlr, MMC_POWER_MODE_POWER_OFF); + } + if (cntlr->ops->setBusWidth != NULL) { + cntlr->ops->setBusWidth(cntlr, BUS_WIDTH1); + } +} + +int32_t MmcCntlrAllocDev(struct MmcCntlr *cntlr, enum MmcDevType devType) +{ + uint32_t len = 0; + struct MmcDevice *mmc = NULL; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + if (devType == MMC_DEV_SDIO || devType == MMC_DEV_COMBO) { + len = (uint32_t)sizeof(struct SdioDevice); + } else if (devType == MMC_DEV_SD) { + len = (uint32_t)sizeof(struct SdDevice); + } else if (devType == MMC_DEV_EMMC) { + len = (uint32_t)sizeof(struct EmmcDevice); + } + + if (len == 0) { + HDF_LOGE("MmcCntlrAllocDev: len is 0, type = %d!", (uint32_t)devType); + return HDF_ERR_INVALID_PARAM; + } + + mmc = (struct MmcDevice *)OsalMemCalloc(len); + if (mmc == NULL) { + HDF_LOGE("MmcCntlrAllocDev: OsalMemCalloc fail!"); + return HDF_ERR_MALLOC_FAIL; + } + mmc->type = devType; + mmc->cntlr = cntlr; + MmcCntlrSetDevice(cntlr, mmc); + return 0; +} + +void MmcCntlrFreeDev(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL || cntlr->curDev == NULL) { + return; + } + + OsalMemFree(cntlr->curDev); + cntlr->curDev = NULL; +} + +bool MmcCntlrSupportUhs(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL) { + return false; + } + + if (cntlr->caps.bits.uhsSdr12 > 0 || + cntlr->caps.bits.uhsSdr25 > 0 || + cntlr->caps.bits.uhsSdr50 > 0 || + cntlr->caps.bits.uhsSdr104 > 0 || + cntlr->caps.bits.uhsDdr50 > 0) { + return true; + } + return false; +} + +bool MmcCntlrSupportHighSpeed400EnhancedStrobe(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL) { + return false; + } + + if (cntlr->caps2.bits.hs400EnhancedStrobe > 0 && + cntlr->caps.bits.cap8Bit > 0 && + cntlr->caps2.bits.hs400Support1v2 > 0 && + cntlr->caps2.bits.hs400Support1v8 > 0) { + return true; + } + return false; +} + +bool MmcCntlrSupportHighSpeed400(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL) { + return false; + } + + if (cntlr->caps.bits.cap8Bit > 0 && + cntlr->caps2.bits.hs400Support1v2 > 0 && + cntlr->caps2.bits.hs400Support1v8 > 0) { + return true; + } + return false; +} + +bool MmcCntlrSupportHighSpeed200(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL) { + return false; + } + + if (cntlr->caps2.bits.hs200Sdr1v8 > 0 || + cntlr->caps2.bits.hs200Sdr1v2 > 0) { + return true; + } + return false; +} + +bool MmcCntlrSdSupportCmd23(struct MmcCntlr *cntlr) +{ + struct SdDevice *dev = NULL; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return false; + } + if (cntlr->curDev->type != MMC_DEV_SD && cntlr->curDev->type != MMC_DEV_COMBO) { + return false; + } + + dev = (struct SdDevice *)cntlr->curDev; + if ((dev->reg.scr.cmdSupport & SD_SCR_SET_BLOCK_COUNT_SUPPORT) > 0) { + return true; + } + return false; +} + +bool MmcCntlrEmmcSupportCmd23(struct MmcCntlr *cntlr) +{ + struct EmmcDevice *dev = NULL; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return false; + } + if (cntlr->curDev->type != MMC_DEV_EMMC) { + return false; + } + + dev = (struct EmmcDevice *)cntlr->curDev; + if ((dev->mmc.reg.csd.ccc & MMC_CSD_CCC_BLOCK_READ) > 0 || + (dev->mmc.reg.csd.ccc & MMC_CSD_CCC_BLOCK_WRITE) > 0) { + return true; + } + return false; +} + +int32_t MmcCntlrAddMsgToQueue(struct MmcCntlr *cntlr, struct MmcCmd *cmd, + int32_t code, bool block) +{ + struct MmcMsg *msg = NULL; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + msg = (struct MmcMsg *)OsalMemCalloc(sizeof(struct MmcMsg)); + if (msg == NULL) { + HDF_LOGE("MmcCntlrAddMsgToQueue: OsalMemCalloc fail!n"); + return HDF_ERR_MALLOC_FAIL; + } + msg->msg.code = code; + msg->msg.data = (void *)cntlr; + msg->msg.block = block; + msg->mmcCmd = cmd; + return MmcCntlrPostMsg(cntlr, msg); +} + +int32_t MmcCntlrAddRequestMsgToQueue(struct MmcCntlr *cntlr, struct MmcCmd *cmd) +{ + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->ops == NULL || cntlr->ops->devPluged == NULL) { + return HDF_PLT_ERR_NO_DEV; + } + if (cntlr->ops->devPluged(cntlr) == false) { + HDF_LOGE("MmcCntlrAddRequestMsgToQueue: host%d dev is unplug!", cntlr->index); + return HDF_PLT_ERR_NO_DEV; + } + + return MmcCntlrAddMsgToQueue(cntlr, cmd, MMC_MSG_REQUEST, true); +} + +int32_t MmcCntlrAddDetectMsgToQueue(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->ops == NULL || cntlr->ops->devPluged == NULL) { + return HDF_PLT_ERR_NO_DEV; + } + + if (cntlr->ops->devPluged(cntlr) == false) { + HDF_LOGD("MmcCntlrAddDetectMsgToQueue: host%d dev is not plugged!", cntlr->index); + return HDF_PLT_ERR_NO_DEV; + } + cntlr->devPluged = true; + return MmcCntlrAddMsgToQueue(cntlr, NULL, MMC_MSG_PLUG, false); +} + +int32_t MmcCntlrAddPlugMsgToQueue(struct MmcCntlr *cntlr) +{ + bool curStatus = false; + int32_t code; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->ops == NULL || cntlr->ops->devPluged == NULL) { + return HDF_PLT_ERR_NO_DEV; + } + + curStatus = cntlr->ops->devPluged(cntlr); + if (curStatus == cntlr->devPluged) { + HDF_LOGD("MmcCntlrAddPlugMsgToQueue: dev plug srtatus not change."); + return HDF_SUCCESS; + } + + if (curStatus == true) { + cntlr->devPluged = true; + code = MMC_MSG_PLUG; + HDF_LOGD("host%d: a dev is plugged!", cntlr->index); + } else { + cntlr->devPluged = false; + code = MMC_MSG_UNPLUG; + HDF_LOGD("host%d: a dev is unplugged!", cntlr->index); + } + return MmcCntlrAddMsgToQueue(cntlr, NULL, code, false); +} + +int32_t MmcCntlrAddSdioRescanMsgToQueue(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->devType != MMC_DEV_SDIO) { + HDF_LOGD("MmcCntlrAddSdioRescanMsgToQueue: not sdio card, do not handle rescan!"); + return HDF_FAILURE; + } + + return MmcCntlrAddMsgToQueue(cntlr, NULL, MMC_MSG_SDIO_RESCAN, true); +} + +static void SdioHandlePendingIrq(struct MmcCntlr *cntlr, struct SdioDevice *dev) +{ + uint8_t val; + int32_t ret; + uint32_t i; + struct SdioFunction *func = dev->curFunction; + + if (func == NULL) { + HDF_LOGE("MmcCntlrHandleSdioPendingIrq: cur func is NULL."); + return; + } + if (dev->irqPending == true && func->irqHandler != NULL) { + func->irqHandler(func); + return; + } + + ret = SdioReadCccrIntPending(cntlr, &val); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcCntlrHandleSdioPendingIrq: read cccr int pending fail! ret = %d.", ret); + return; + } + + for (i = 0; i < SDIO_MAX_FUNCTION_NUMBER; i++) { + if ((val & (1 << (i + 1))) == 0) { + continue; + } + func = dev->sdioFunc[i]; + if (func == NULL) { + HDF_LOGD("MmcCntlrHandleSdioPendingIrq: function%d not exist.", i + 1); + continue; + } + if (func->irqHandler == NULL) { + HDF_LOGD("MmcCntlrHandleSdioPendingIrq: function%d irq handler not exist.", i + 1); + continue; + } + func->irqHandler(func); + } +} + +static int32_t SdioIrqThreadWorker(void *data) +{ + int32_t ret; + struct SdioDevice *dev = (struct SdioDevice *)data; + struct MmcCntlr *cntlr = NULL; + + if (dev == NULL) { + HDF_LOGE("SdioIrqThreadWorker: data is NULL."); + return HDF_FAILURE; + } + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioIrqThreadWorker: cntlr is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + while (true) { + /* wait envent */ + ret = OsalSemWait(&dev->sem, HDF_WAIT_FOREVER); + if (ret != HDF_SUCCESS) { + continue; + } + SdioHandlePendingIrq(cntlr, dev); + dev->irqPending = false; + if (cntlr->caps.bits.sdioIrq > 0 && cntlr->ops != NULL && cntlr->ops->setSdioIrq != NULL) { + (void)cntlr->ops->setSdioIrq(cntlr, true); + } + } + + return HDF_SUCCESS; +} + +int32_t MmcCntlrCreatSdioIrqThread(struct MmcCntlr *cntlr) +{ + int32_t ret; + struct OsalThreadParam config = {0}; + struct SdioDevice *dev = NULL; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + dev = (struct SdioDevice *)cntlr->curDev; + ret = OsalSemInit(&dev->sem, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcCntlrCreatSdioIrqThread: sem init fail."); + return ret; + } + + ret = OsalThreadCreate(&dev->thread, (OsalThreadEntry)SdioIrqThreadWorker, dev); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcCntlrCreatSdioIrqThread: thread create fail."); + (void)OsalSemDestroy(&dev->sem); + return ret; + } + + config.name = "SdioIrqTask"; + config.priority = OSAL_THREAD_PRI_HIGHEST; + config.stackSize = SDIO_IRQ_TASK_STACK_SIZE; + ret = OsalThreadStart(&dev->thread, &config); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcCntlrCreatSdioIrqThread: thread start fail."); + OsalThreadDestroy(&dev->thread); + (void)OsalSemDestroy(&dev->sem); + return ret; + } + dev->threadRunning = true; + if (cntlr->caps.bits.sdioIrq > 0 && cntlr->ops != NULL && cntlr->ops->setSdioIrq != NULL) { + (void)cntlr->ops->setSdioIrq(cntlr, true); + } + return HDF_SUCCESS; +} + +void MmcCntlrDestroySdioIrqThread(struct MmcCntlr *cntlr) +{ + struct SdioDevice *dev = NULL; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return; + } + + dev = (struct SdioDevice *)cntlr->curDev; + (void)OsalThreadDestroy(&dev->thread); + (void)OsalSemDestroy(&dev->sem); + dev->threadRunning = true; +} + +void MmcCntlrNotifySdioIrqThread(struct MmcCntlr *cntlr) +{ + struct SdioDevice *dev = NULL; + + if (cntlr == NULL || cntlr->curDev == NULL) { + HDF_LOGD("MmcCntlrNotifySdioIrqThread: cntlr or curDev is null!"); + return; + } + if (cntlr->curDev->type != MMC_DEV_SDIO && cntlr->curDev->type != MMC_DEV_COMBO) { + return; + } + dev = (struct SdioDevice *)cntlr->curDev; + if (dev->threadRunning == true) { + dev->irqPending = true; + /* notify the worker thread */ + (void)OsalSemPost(&dev->sem); + } +} + +static void MmcCntlrParseCapability(const struct DeviceResourceNode *node, + struct DeviceResourceIface *drsOps, struct MmcCntlr *cntlr) +{ + int32_t ret; + + ret = drsOps->GetUint16(node, "voltDef", &(cntlr->voltDef), 0); + if (ret != HDF_SUCCESS) { + cntlr->voltDef = 0; + } + ret = drsOps->GetUint32(node, "freqMin", &(cntlr->freqMin), 0); + if (ret != HDF_SUCCESS) { + cntlr->freqMin = 0; + } + ret = drsOps->GetUint32(node, "freqMax", &(cntlr->freqMax), 0); + if (ret != HDF_SUCCESS) { + cntlr->freqMax = 0; + } + ret = drsOps->GetUint32(node, "freqDef", &(cntlr->freqDef), 0); + if (ret != HDF_SUCCESS) { + cntlr->freqDef = 0; + } + ret = drsOps->GetUint32(node, "ocrDef", &(cntlr->ocrDef.ocrData), 0); + if (ret != HDF_SUCCESS) { + cntlr->ocrDef.ocrData = 0; + } + + ret = drsOps->GetUint32(node, "caps", &(cntlr->caps.capsData), 0); + if (ret != HDF_SUCCESS) { + cntlr->caps.capsData = 0; + } + ret = drsOps->GetUint32(node, "caps2", &(cntlr->caps2.caps2Data), 0); + if (ret != HDF_SUCCESS) { + cntlr->caps2.caps2Data = 0; + } + + ret = drsOps->GetUint32(node, "maxBlkNum", &(cntlr->maxBlkNum), 0); + if (ret != HDF_SUCCESS) { + cntlr->maxBlkNum = 0; + } + ret = drsOps->GetUint32(node, "maxBlkSize", &(cntlr->maxBlkSize), 0); + if (ret != HDF_SUCCESS) { + cntlr->maxBlkSize = 0; + } + cntlr->maxReqSize = cntlr->maxBlkNum * cntlr->maxBlkSize; +} + +int32_t MmcCntlrParse(struct MmcCntlr *cntlr, struct HdfDeviceObject *obj) +{ + const struct DeviceResourceNode *node = NULL; + struct DeviceResourceIface *drsOps = NULL; + int32_t ret; + + if (obj == NULL || cntlr == NULL) { + HDF_LOGE("MmcCntlrParse: input param is NULL."); + return HDF_FAILURE; + } + + node = obj->property; + if (node == NULL) { + HDF_LOGE("MmcCntlrParse: drs node is NULL."); + return HDF_FAILURE; + } + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint16 == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("MmcCntlrParse: invalid drs ops fail!"); + return HDF_FAILURE; + } + + ret = drsOps->GetUint16(node, "hostId", &(cntlr->index), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcCntlrParse: read hostId fail!"); + return ret; + } + HDF_LOGD("MmcCntlrParse: hostId = %d", cntlr->index); + + ret = drsOps->GetUint32(node, "devType", &(cntlr->devType), 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcCntlrParse: read devType fail!"); + return ret; + } + HDF_LOGD("MmcCntlrParse: devType = %d", cntlr->devType); + + MmcCntlrParseCapability(node, drsOps, cntlr); + return HDF_SUCCESS; +} + +int32_t MmcDeviceAdd(struct MmcDevice *mmc) +{ + int32_t ret; + + if (mmc == NULL || mmc->cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (mmc->type >= MMC_DEV_INVALID) { + return HDF_PLT_ERR_DEV_TYPE; + } + if (mmc->secSize == 0) { + mmc->secSize = MMC_SEC_SIZE; + } else { + HDF_LOGE("MmcDeviceAdd: invalid sector size:%u", mmc->secSize); + return HDF_ERR_INVALID_PARAM; + } + if (mmc->type != MMC_DEV_SDIO && mmc->capacity == 0) { + HDF_LOGE("MmcDeviceAdd: invalid capacity:%u", mmc->capacity); + return HDF_ERR_INVALID_PARAM; + } + if (mmc->type != MMC_DEV_SDIO && mmc->eraseSize == 0) { + HDF_LOGE("MmcDeviceAdd: invalid erase size:%u", mmc->eraseSize); + return HDF_ERR_INVALID_PARAM; + } + mmc->device.magic = mmc->cntlr->device.magic + MMC_CNTLR_NR_MAX; + + if (MmcCntlrGet(mmc->cntlr) == NULL) { + return HDF_PLT_ERR_DEV_GET; + } + + mmc->device.manager = PlatformManagerGet(PLATFORM_MODULE_MMC); + ret = PlatformDeviceAdd(&mmc->device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcDeviceAdd: mmc device add fail"); + MmcCntlrPut(mmc->cntlr); + return ret; + } + + if (mmc->type == MMC_DEV_EMMC || mmc->type == MMC_DEV_SD || mmc->type == MMC_DEV_COMBO) { + ret = MmcBlockAdd(mmc); + if (ret != HDF_SUCCESS) { + MmcCntlrPut(mmc->cntlr); + PlatformDeviceDel(&mmc->device); + return ret; + } + } + return HDF_SUCCESS; +} + +void MmcDeviceRemove(struct MmcDevice *mmc) +{ + if (mmc == NULL) { + return; + } + if (mmc->type == MMC_DEV_EMMC || mmc->type == MMC_DEV_SD || mmc->type == MMC_DEV_COMBO) { + MmcBlockDel(mmc); + } + PlatformDeviceDel(&mmc->device); + MmcCntlrPut(mmc->cntlr); +} + +struct MmcDevice *MmcDeviceGet(struct MmcDevice *mmc) +{ + if (mmc == NULL) { + return NULL; + } + + if (PlatformDeviceGet(&mmc->device) == NULL) { + HDF_LOGE("MmcDeviceAdd: get device ref fail!"); + return NULL; + } + return mmc; +} + +void MmcDevicePut(struct MmcDevice *mmc) +{ + if (mmc == NULL) { + return; + } + PlatformDevicePut(&mmc->device); +} + +void MmcDeviceAddOps(struct MmcDevice *mmc, void *ops) +{ + if (mmc->type >= MMC_DEV_INVALID) { + HDF_LOGE("MmcDeviceAddOps: dev type error!"); + return; + } + + if (mmc->type == MMC_DEV_SDIO || mmc->type == MMC_DEV_COMBO) { + SdioDeviceAddOps((struct SdioDevice *)mmc, ops); + return; + } + + if (mmc->type == MMC_DEV_EMMC) { + EmmcDeviceAddOps((struct EmmcDevice *)mmc, ops); + } +} + +static void MmcDeviceFillRwInfo(struct MmcRwData *info, uint8_t *buf, + bool writeFlag, size_t startSec, size_t nSec) +{ + info->buf = buf; + info->writeFlag = writeFlag; + info->startSector = startSec; + info->sectors = nSec; +} + +ssize_t MmcDeviceRead(struct MmcDevice *mmc, uint8_t *buf, size_t startSec, size_t nSec) +{ + struct MmcCmd cmd = {0}; + struct MmcData data = {0}; + struct MmcRwData info = {0}; + size_t curSec = nSec; + size_t curStartSec = startSec; + size_t readSec; + ssize_t ret; + + if (mmc == NULL) { + HDF_LOGE("MmcDeviceRead: mmc is null!"); + return HDF_ERR_INVALID_OBJECT; + } + if (buf == NULL) { + HDF_LOGE("MmcDeviceRead: buf is null!"); + return HDF_ERR_INVALID_PARAM; + } + + do { + if (curSec >= MMC_MAX_SECTOR_NUM) { + readSec = MMC_MAX_SECTOR_NUM; + } else { + readSec = curSec; + } + MmcDeviceFillRwInfo(&info, buf, false, curStartSec, readSec); + if (mmc->cntlr->detecting == true) { + ret = MmcSendReadWriteBlocks(mmc->cntlr, &info); + } else { + cmd.data = &data; + MmcSetupReadWriteBlocksCmd(mmc, &cmd, &info); + ret = MmcCntlrAddRequestMsgToQueue(mmc->cntlr, &cmd); + } + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcDeviceRead: fail!"); + return ret; + } + curSec -= readSec; + curStartSec += readSec; + buf += (readSec * BYTES_PER_BLOCK); + } while (curSec > 0); + + return nSec; +} + +ssize_t MmcDeviceWrite(struct MmcDevice *mmc, uint8_t *buf, size_t startSec, size_t nSec) +{ + struct MmcCmd cmd = {0}; + struct MmcData data = {0}; + struct MmcRwData info = {0}; + size_t curSec = nSec; + size_t curStartSec = startSec; + size_t writeSec; + ssize_t ret; + + if (mmc == NULL) { + HDF_LOGE("MmcDeviceWrite: mmc is null!"); + return HDF_ERR_INVALID_OBJECT; + } + if (buf == NULL) { + HDF_LOGE("MmcDeviceWrite: buf is null!"); + return HDF_ERR_INVALID_PARAM; + } + + do { + if (curSec >= MMC_MAX_SECTOR_NUM) { + writeSec = MMC_MAX_SECTOR_NUM; + } else { + writeSec = curSec; + } + MmcDeviceFillRwInfo(&info, buf, true, curStartSec, writeSec); + if (mmc->cntlr->detecting == true) { + ret = MmcSendReadWriteBlocks(mmc->cntlr, &info); + } else { + cmd.data = &data; + MmcSetupReadWriteBlocksCmd(mmc, &cmd, &info); + ret = MmcCntlrAddRequestMsgToQueue(mmc->cntlr, &cmd); + } + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcDeviceWrite: fail!"); + return ret; + } + curSec -= writeSec; + curStartSec += writeSec; + buf += (writeSec * BYTES_PER_BLOCK); + } while (curSec > 0); + + return nSec; +} + +ssize_t MmcDeviceErase(struct MmcDevice *mmc, size_t startSec, size_t nSec) +{ + size_t curSec = nSec; + size_t curStartSec = startSec; + size_t eraseSec; + ssize_t ret; + + if (mmc == NULL) { + HDF_LOGE("MmcDeviceErase: mmc is null!"); + return HDF_ERR_INVALID_OBJECT; + } + + do { + if (curSec > MMC_MAX_ERASE_SECTOR) { + eraseSec = MMC_MAX_ERASE_SECTOR; + } else { + eraseSec = curSec; + } + ret = MmcSendErase(mmc->cntlr, curStartSec, eraseSec); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcDeviceErase: fail!"); + return ret; + } + curSec -= eraseSec; + curStartSec += eraseSec; + } while (curSec > 0); + + return HDF_SUCCESS; +} diff --git a/support/platform/src/mmc/mmc_dispatch.c b/support/platform/src/mmc/mmc_dispatch.c new file mode 100644 index 00000000..2013b8ab --- /dev/null +++ b/support/platform/src/mmc/mmc_dispatch.c @@ -0,0 +1,118 @@ +/* + * 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 "mmc_dispatch.h" +#include "hdf_log.h" +#include "mmc_corex.h" +#include "mmc_emmc.h" +#include "mmc_sdio.h" + +static int32_t MmcCmdDevPresent(struct MmcCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + (void)data; + if (reply == NULL) { + return HDF_ERR_INVALID_PARAM; + } + if (!HdfSbufWriteUint8(reply, MmcCntlrDevPresent(cntlr))) { + HDF_LOGE("MmcCmdDevPresent: write reply sbuf fail!"); + return HDF_ERR_IO; + } + return HDF_SUCCESS; +} + +static int32_t MmcDispatch(struct MmcCntlr *cntlr, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + int32_t ret; + + switch (cmd) { + case MMC_CMD_DEV_PRESENT: + ret = MmcCmdDevPresent(cntlr, data, reply); + break; + default: + ret = HDF_ERR_NOT_SUPPORT; + break; + } + return ret; +} + +static int32_t EmmcCmdGetCid(struct MmcCntlr *cntlr, struct HdfSBuf *reply) +{ + int32_t ret; + uint8_t cid[EMMC_CID_LEN] = {0}; + + if (reply == NULL || cntlr == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + ret = EmmcDeviceGetCid((struct EmmcDevice *)cntlr->curDev, cid, EMMC_CID_LEN); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcCmdGetCid: get cid fail!"); + return ret; + } + + if (HdfSbufWriteBuffer(reply, cid, EMMC_CID_LEN) == false) { + HDF_LOGE("MmcCmdGetCid: write back cid fail!"); + return HDF_ERR_IO; + } + + return HDF_SUCCESS; +} + +static int32_t EmmcDispatch(struct MmcCntlr *cntlr, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + int32_t ret; + (void)data; + + switch (cmd) { + case EMMC_CMD_GET_CID: + ret = EmmcCmdGetCid(cntlr, reply); + break; + default: + ret = HDF_ERR_NOT_SUPPORT; + break; + } + return ret; +} + +static int32_t SdioDispatch(struct MmcCntlr *cntlr, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + (void)cntlr; + (void)cmd; + (void)data; + (void)reply; + return HDF_ERR_NOT_SUPPORT; +} + +int32_t MmcIoDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + int32_t ret; + struct MmcCntlr *cntlr = NULL; + + if (client == NULL || client->device == NULL) { + HDF_LOGE("MmcIoDispatch: client or hdf dev obj is NULL"); + return HDF_ERR_INVALID_OBJECT; + } + + cntlr = (struct MmcCntlr *)client->device->service; + if (cntlr == NULL) { + HDF_LOGE("MmcIoDispatch: service is NULL"); + return HDF_ERR_INVALID_OBJECT; + } + + if (cmd < MMC_CMD_MAX) { + ret = MmcDispatch(cntlr, cmd, data, reply); + } else if (cmd < EMMC_CMD_MAX) { + ret = EmmcDispatch(cntlr, cmd, data, reply); + } else if (cmd < SDIO_CMD_MAX) { + ret = SdioDispatch(cntlr, cmd, data, reply); + } else { + ret = HDF_ERR_NOT_SUPPORT; + } + + return ret; +} diff --git a/support/platform/src/mmc/mmc_emmc.c b/support/platform/src/mmc/mmc_emmc.c new file mode 100644 index 00000000..e4495e3c --- /dev/null +++ b/support/platform/src/mmc/mmc_emmc.c @@ -0,0 +1,57 @@ +/* + * 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 "mmc_emmc.h" +#include "securec.h" + +#define HDF_LOG_TAG mmc_emmc_c + +static int32_t EmmcDeviceDefaultGetCid(struct EmmcDevice *dev, uint8_t *cid, uint32_t len) +{ + struct MmcDevice *mmc = (struct MmcDevice *)dev; + + if (memcpy_s(cid, sizeof(uint8_t) * len, (uint8_t *)(mmc->reg.rawCid), + sizeof(mmc->reg.rawCid)) != EOK) { + HDF_LOGE("EmmcDeviceDefaultGetCid: memcpy_s fail, size = %d!", len); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static struct EmmcDeviceOps g_emmcOps = { + .getCid = EmmcDeviceDefaultGetCid, +}; + +int32_t EmmcDeviceGetCid(struct EmmcDevice *dev, uint8_t *cid, uint32_t len) +{ + if (dev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + if (cid == NULL || len == 0) { + return HDF_ERR_INVALID_PARAM; + } + if (dev->emmcOps == NULL || dev->emmcOps->getCid == NULL) { + HDF_LOGE("EmmcDeviceGetCid: ops or getCid is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + return dev->emmcOps->getCid(dev, cid, len); +} + +void EmmcDeviceAddOps(struct EmmcDevice *dev, void *ops) +{ + if (dev == NULL) { + HDF_LOGE("EmmcDeviceAddOps: dev is NULL."); + return; + } + if (ops == NULL) { + dev->emmcOps = &g_emmcOps; + HDF_LOGD("EmmcDeviceAddOps: use default ops."); + } else { + dev->emmcOps = (struct EmmcDeviceOps *)ops; + } +} diff --git a/support/platform/src/mmc/mmc_if.c b/support/platform/src/mmc/mmc_if.c new file mode 100644 index 00000000..8b37d0d7 --- /dev/null +++ b/support/platform/src/mmc/mmc_if.c @@ -0,0 +1,114 @@ +/* + * 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 "mmc_if.h" +#ifndef __USER__ +#include "devsvc_manager_clnt.h" +#include "mmc_corex.h" +#endif +#include "hdf_base.h" +#ifdef __USER__ +#include "hdf_io_service_if.h" +#endif +#include "hdf_log.h" +#include "osal_mem.h" +#include "securec.h" + +#define HDF_LOG_TAG mmc_if_c + +#define MMC_SVC_NAME_LEN 32 + +static void *MmcCntlrObjGetByNumber(int16_t id) +{ + void *object = NULL; + char *serviceName = NULL; + + if (id < 0) { + HDF_LOGE("MmcCntlrObjGetByNumber: invalid id:%d", id); + return NULL; + } + serviceName = OsalMemCalloc(MMC_SVC_NAME_LEN + 1); + if (serviceName == NULL) { + HDF_LOGE("MmcCntlrObjGetByNumber: OsalMemCalloc fail!"); + return NULL; + } + if (snprintf_s(serviceName, MMC_SVC_NAME_LEN + 1, MMC_SVC_NAME_LEN, + "HDF_PLATFORM_MMC_%d", id) < 0) { + HDF_LOGE("MmcCntlrObjGetByNumber: format service name fail!"); + goto __ERR; + } + +#ifdef __USER__ + object = (void *)HdfIoServiceBind(serviceName); +#else + object = (void *)MmcCntlrGetByNr(id); +#endif + if (object == NULL) { + HDF_LOGE("MmcCntlrObjGetByNumber: get service fail!"); + } else { + HDF_LOGD("MmcCntlrObjGetByNumber: success"); + } + +__ERR: + OsalMemFree(serviceName); + return object; +} + +DevHandle MmcOpen(int16_t id) +{ + return (DevHandle)MmcCntlrObjGetByNumber(id); +} + +void MmcClose(DevHandle handle) +{ + if (handle != NULL) { +#ifdef __USER__ + HdfIoServiceRecycle((struct HdfIoService *)handle); +#endif + } +} + +bool MmcDevPresent(DevHandle handle) +{ + if (handle == NULL) { + return false; + } +#ifdef __USER__ + int32_t ret; + uint8_t present = 0; + struct HdfSBuf *reply = NULL; + struct HdfIoService *service = (struct HdfIoService *)handle; + + reply = HdfSBufObtainDefaultSize(); + if (reply == NULL) { + HDF_LOGE("MmcDevPresent: failed to obtain reply!"); + return false; + } + + if (service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) { + HDF_LOGE("MmcDevPresent: dispatcher or Dispatch is NULL!"); + goto __EXIT; + } + ret = service->dispatcher->Dispatch(&service->object, MMC_CMD_DEV_PRESENT, + NULL, reply); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MmcDevPresent: failed to send service call:%d", ret); + goto __EXIT; + } + + if (HdfSbufReadUint8(reply, &present) == false) { + HDF_LOGE("MmcDevPresent: read present fail!"); + goto __EXIT; + } +__EXIT: + HdfSBufRecycle(reply); + return (present != 0); +#else + return MmcCntlrDevPresent((struct MmcCntlr *)handle); +#endif +} diff --git a/support/platform/src/mmc/mmc_protocol.c b/support/platform/src/mmc/mmc_protocol.c new file mode 100644 index 00000000..304c3e12 --- /dev/null +++ b/support/platform/src/mmc/mmc_protocol.c @@ -0,0 +1,4119 @@ +/* + * 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 "mmc_emmc.h" +#include "mmc_sd.h" +#include "mmc_sdio.h" +#include "securec.h" + +#define HDF_LOG_TAG mmc_protocol_c + +#define INIT_CMD_RETRY_TIMES 100 +#define MMC_CMD_DEFAULT_RETRY_TIMES 3 +#define SEND_STATUS_CMD_RETRY_TIMES 100 +#define STOP_TRANSMISSION_CMD_RETRY_TIMES 5 +#define BITS_NUMBER_OF_4_BYTES 32 + +/* TRAN_SPEED: Frequency unit 0 = 100KHz, 1 = 1MHz, 2 = 10MHz, 3 = 100MHz, 4...7 = reserved */ +uint32_t g_tranSpeedUnit[] = { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 }; + +/* TAAC: Time unit 0 = 1ns, 1 = 10ns, 2 = 100ns, 3 = 1us, 4 = 10us, 5 = 100us, 6 = 1ms, 7 = 10ms */ +uint32_t g_taccUnit[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 }; + +/* + * TRAN_SPEED/TAAC: Multiplier factor 0 = reserved, 1 = 1.0, 2 = 1.2, 3 = 1.3, 4 = 1.5, 5 = 2.0, 6 = 2.5, + * 7 = 3.0, 8 = 3.5, 9 = 4.0, A = 4.5, B = 5.0, C = 5.5, D = 6.0, E = 7.0, F = 8.0 + */ +uint32_t g_commFactor[] = { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; + +/* Little-endian and Big-endian interconversion. */ +static uint32_t MmcEndianConversion(uint32_t x) +{ + uint32_t val = x; + + return (uint32_t)( + (((uint32_t)(val) & (uint32_t)0x000000ffUL) << 24) | + (((uint32_t)(val) & (uint32_t)0x0000ff00UL) << 8) | + (((uint32_t)(val) & (uint32_t)0x00ff0000UL) >> 8) | + (((uint32_t)(val) & (uint32_t)0xff000000UL) >> 24)); +} + +/* Decoding algorithm */ +static uint32_t MmcParseBits(uint32_t *data, uint32_t bitsLen, uint32_t start, uint32_t size) +{ + uint32_t index; + uint32_t shift; + uint32_t ret; + + if (start >= bitsLen || size == 0) { + HDF_LOGE("MmcParseBits: input invalid!"); + return 0; + } + if (size > BITS_NUMBER_OF_4_BYTES) { + HDF_LOGE("MmcParseBits: not support!"); + return 0; + } + + index = (bitsLen / BITS_NUMBER_OF_4_BYTES) - (start / BITS_NUMBER_OF_4_BYTES) - 1; + shift = start & (BITS_NUMBER_OF_4_BYTES - 1); + ret = data[index] >> shift; + if (size + shift > BITS_NUMBER_OF_4_BYTES) { + ret |= data[index - 1] << (BITS_NUMBER_OF_4_BYTES - shift); + } + + if (size < BITS_NUMBER_OF_4_BYTES) { + return (ret & ((1u << size) - 1)); + } + return (ret & 0xFFFFFFFF); +} + +static int32_t MmcSendCmd(struct MmcCntlr *cntlr, struct MmcCmd *cmd, struct MmcData *data, uint32_t retryTimes) +{ + uint32_t i; + int32_t ret; + + if (cntlr == NULL || cmd == NULL || retryTimes == 0) { + return HDF_ERR_INVALID_PARAM; + } + if (cntlr->ops == NULL || cntlr->ops->request == NULL) { + return HDF_ERR_NOT_SUPPORT; + } + + cmd->data = data; + for (i = 0; i < retryTimes; i++) { + ret = MmcCntlrDoRequest(cntlr, cmd); + if (ret != HDF_SUCCESS) { + continue; + } + if (cmd->returnError != HDF_SUCCESS) { + continue; + } + if (data != NULL && data->returnError != HDF_SUCCESS) { + continue; + } + break; + } + if (data == NULL) { + return cmd->returnError; + } + if (cmd->returnError != HDF_SUCCESS) { + return cmd->returnError; + } + if (data->returnError != HDF_SUCCESS) { + return data->returnError; + } + return HDF_SUCCESS; +} + +static void MmcGoIdleState(struct MmcCntlr *cntlr) +{ + struct MmcCmd cmd = {0}; + + /* Command GO_IDLE_STATE (CMD0) is the software reset command and sets all cards into Idle State. */ + cmd.cmdCode = GO_IDLE_STATE; + /* [31:0] stuff bits. */ + cmd.argument = 0; + /* Broadcast Commands (bc), no response. */ + cmd.respType = MMC_RESP_SPI_R1 | MMC_RESP_NONE | MMC_CMD_TYPE_BC; + (void)MmcSendCmd(cntlr, &cmd, NULL, 1); + OsalMDelay(1); +} + +static int32_t MmcSendOpCond(struct MmcCntlr *cntlr, uint32_t arg, uint32_t *ocr) +{ + struct MmcCmd cmd = {0}; + int32_t err; + uint32_t i; + + /* + * The SEND_OP_COND (CMD1) command is designed to provide MultiMediaCard hosts with a mechanism + * to identify and reject cards which do not match the VDD range desired by the host. + */ + cmd.cmdCode = SEND_OP_COND; + /* [31:0] OCR. */ + cmd.argument = arg; + cmd.respType = MMC_RESP_SPI_R1 | MMC_RESP_R3 | MMC_CMD_TYPE_BCR; + /* + * The host must poll the card (by repeatedly sending CMD1 or ACMD41) until the 'in-idle-state' bit in + * the card response indicates (by being set to 0) that the card completed its initialization processes + * and is ready for the next command. + */ + for (i = 0; i < INIT_CMD_RETRY_TIMES; i++) { + err = MmcSendCmd(cntlr, &cmd, NULL, 1); + if (err != HDF_SUCCESS) { + break; + } + if (arg == 0 || (cmd.resp[0] & MMC_CARD_BUSY_STATUS) > 0) { + break; + } + + err = HDF_ERR_TIMEOUT; + OsalMDelay(10); + } + + if (ocr != NULL) { + *ocr = cmd.resp[0]; + } + return err; +} + +static int32_t MmcAllSendCid(struct MmcCntlr *cntlr) +{ + struct MmcCmd cmd = {0}; + uint32_t *cid = NULL; + int32_t err; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + cmd.cmdCode = ALL_SEND_CID; + /* [31:0] stuff bits. */ + cmd.argument = 0; + /* Broadcast Commands with Response(bcr). */ + cmd.respType = MMC_RESP_R2 | MMC_CMD_TYPE_BCR; + err = MmcSendCmd(cntlr, &cmd, NULL, MMC_CMD_DEFAULT_RETRY_TIMES); + if (err != HDF_SUCCESS) { + return err; + } + cid = cntlr->curDev->reg.rawCid; + if (memcpy_s(cid, sizeof(cntlr->curDev->reg.rawCid), cmd.resp, sizeof(cmd.resp)) != EOK) { + HDF_LOGE("MmcAllSendCid: memcpy_s fail!"); + return HDF_FAILURE; + } + return err; +} + +static int32_t MmcSetRelativeAddr(struct MmcCntlr *cntlr) +{ + struct MmcCmd cmd = {0}; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + cmd.cmdCode = SET_RELATIVE_ADDR; + /* [31:16] RCA, [15:0] stuff bits. */ + cmd.argument = (cntlr->curDev->reg.rca << 16); + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_AC; + return MmcSendCmd(cntlr, &cmd, NULL, MMC_CMD_DEFAULT_RETRY_TIMES); +} + +static int32_t MmcSelectCard(struct MmcCntlr *cntlr) +{ + struct MmcCmd cmd = {0}; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + cmd.cmdCode = SELECT_CARD; + /* [31:16] RCA, [15:0] stuff bits. */ + cmd.argument = (cntlr->curDev->reg.rca << 16); + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_AC; + return MmcSendCmd(cntlr, &cmd, NULL, MMC_CMD_DEFAULT_RETRY_TIMES); +} + +static int32_t MmcSendExtCsd(struct MmcCntlr *cntlr, uint8_t *extCsd, uint32_t len) +{ + struct MmcCmd cmd = {0}; + struct MmcData data = {0}; + + cmd.cmdCode = SEND_EXT_CSD; + cmd.argument = 0; + cmd.respType = MMC_RESP_SPI_R1 | MMC_RESP_R1 | MMC_CMD_TYPE_ADTC; + + /* The card sends the EXT_CSD register as a block of data, 512 bytes long. */ + data.blockSize = len; + data.blockNum = 1; + data.dataFlags = DATA_READ; + data.dataBuffer = extCsd; + + return MmcSendCmd(cntlr, &cmd, &data, 1); +} + +static int32_t MmcSendCsd(struct MmcCntlr *cntlr) +{ + struct MmcCmd cmd = {0}; + uint32_t *csd = NULL; + int32_t err; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + cmd.cmdCode = SEND_CSD; + cmd.argument = (cntlr->curDev->reg.rca << 16); + cmd.respType = MMC_RESP_R2 | MMC_CMD_TYPE_AC; + err = MmcSendCmd(cntlr, &cmd, NULL, MMC_CMD_DEFAULT_RETRY_TIMES); + if (err != HDF_SUCCESS) { + return err; + } + csd = cntlr->curDev->reg.rawCsd; + if (memcpy_s(csd, sizeof(cntlr->curDev->reg.rawCsd), cmd.resp, sizeof(cmd.resp)) != EOK) { + HDF_LOGE("memcpy_s fail!"); + return HDF_FAILURE; + } + return err; +} + +int32_t MmcSendStatus(struct MmcCntlr *cntlr, uint32_t *status) +{ + struct MmcCmd cmd = {0}; + int32_t error; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + cmd.cmdCode = SEND_STATUS; + /* [31:16] RCA, [15:0] stuff bits. */ + cmd.argument = (cntlr->curDev->reg.rca << 16); + cmd.respType = MMC_RESP_SPI_R2 | MMC_RESP_R1 | MMC_CMD_TYPE_AC; + error = MmcSendCmd(cntlr, &cmd, NULL, MMC_CMD_DEFAULT_RETRY_TIMES); + if (error != HDF_SUCCESS) { + return error; + } + if (status != NULL) { + *status = cmd.resp[0]; + } + return error; +} + +static int32_t MmcSwitch(struct MmcCntlr *cntlr, uint8_t set, uint8_t index, uint8_t value) +{ + int32_t error; + struct MmcCmd cmd = {0}; + uint32_t status; + + cmd.cmdCode = SWITCH; + /* + * [31:26] Set to 0; [25:24] Access; [23:16] Index; + * [15:8] Value; [7:3] Set to 0; [2:0] Cmd Set. + */ + cmd.argument = (EMMC_EXT_CSD_WRITE_BYTE << 24) + | (index << 16) + | (value << 8) + | set; + cmd.respType = MMC_RESP_SPI_R1B | MMC_RESP_R1B | MMC_CMD_TYPE_AC; + error = MmcSendCmd(cntlr, &cmd, NULL, MMC_CMD_DEFAULT_RETRY_TIMES); + if (error != HDF_SUCCESS) { + HDF_LOGE("MmcSwitch: send cmd fail!"); + return error; + } + + /* + * The SWITCH command response is of type R1b, therefore, the host should read the card status, using + * SEND_STATUS command, after the busy signal is de-asserted, to check the result of the SWITCH operation. + */ + do { + error = MmcSendStatus(cntlr, &status); + if (error != HDF_SUCCESS) { + HDF_LOGE("MmcSwitch: send status cmd fail!"); + return error; + } + } while ((!(status & READY_FOR_DATA)) || MmcCntlrDevBusy(cntlr) == true); + + /* + * When the host tries to access a partition which has not been created before, the devices sets the + * SWITCH_ERROR bit in the status register and will not change the PARTITION_ACCESS bits. + */ + if ((status & SWITCH_ERROR) > 0) { + return HDF_MMC_ERR_SWITCH_FAIL; + } + return error; +} + +static int32_t MmcAppCmd(struct MmcCntlr *cntlr, uint32_t acmd) +{ + int32_t err; + struct MmcCmd cmd = {0}; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + /* + * After the bus is activated the host will request the cards to send their valid operation conditions + * (ACMD41 preceding with APP_CMD - CMD55 with RCA = 0x0000). + */ + cmd.cmdCode = APP_CMD; + if (acmd != SD_ACMD_OP_COND) { + /* [31:16] RCA, [15:0] stuff bits */ + cmd.argument = (cntlr->curDev->reg.rca << 16); + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_AC; + } else { + cmd.argument = 0; + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_BCR; + } + err = MmcSendCmd(cntlr, &cmd, NULL, 1); + if (err != HDF_SUCCESS) { + return err; + } + if (!(cmd.resp[0] & IS_APP_CMD)) { + return HDF_FAILURE; + } + return err; +} + +static int32_t MmcWaitCardReady(struct MmcCntlr *cntlr) +{ + int error; + uint32_t status; + int32_t retryTimes = SEND_STATUS_CMD_RETRY_TIMES; + + do { + error = MmcSendStatus(cntlr, &status); + if (error != HDF_SUCCESS) { + return error; + } + + if (retryTimes >= 0) { + retryTimes--; + OsalMSleep(10); + } else { + return HDF_ERR_TIMEOUT; + } + } while (!(status & READY_FOR_DATA) || (MMC_CARD_CURRENT_STATE(status) == STATE_PRG)); + return error; +} + +int32_t MmcStopTransmission(struct MmcCntlr *cntlr, bool writeFlag, uint32_t *stopStatus) +{ + int32_t err; + struct MmcCmd cmd = {0}; + + cmd.cmdCode = STOP_TRANSMISSION; + /* R1 for read cases and R1b for write cases. */ + if (writeFlag == true) { + cmd.respType = MMC_RESP_R1B | MMC_CMD_TYPE_AC; + } else { + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_AC; + } + err = MmcSendCmd(cntlr, &cmd, NULL, STOP_TRANSMISSION_CMD_RETRY_TIMES); + if (err != HDF_SUCCESS) { + return err; + } + + *stopStatus = cmd.resp[0]; + /* No need to check card status in case of read. */ + if (writeFlag == false) { + return err; + } + return MmcWaitCardReady(cntlr); +} + +int32_t MmcSendTuning(struct MmcCntlr *cntlr, uint32_t cmdCode, bool sendStop) +{ + struct MmcCmd cmd = {0}; + struct MmcData data = {0}; + /* Tuning Block Pattern UHS-I. */ + uint8_t tuningBlk4bit[] = { + 0xFF, 0x0F, 0xFF, 0x00, 0xFF, 0xCC, 0xC3, 0xCC, 0xC3, 0x3C, 0xCC, 0xFF, + 0xFE, 0xFF, 0xFE, 0xEF, 0xFF, 0xDF, 0xFF, 0xDD, 0xFF, 0xFB, 0xFF, 0xFB, + 0xBF, 0xFF, 0x7F, 0xFF, 0x77, 0xF7, 0xBD, 0xEF, 0xFF, 0xF0, 0xFF, 0xF0, + 0x0F, 0xFC, 0xCC, 0x3C, 0xCC, 0x33, 0xCC, 0xCF, 0xFF, 0xEF, 0xFF, 0xEE, + 0xFF, 0xFD, 0xFF, 0xFD, 0xDF, 0xFF, 0xBF, 0xFF, 0xBB, 0xFF, 0xF7, 0xFF, + 0xF7, 0x7f, 0x7B, 0xDE, + }; + /* Tuning block pattern for 8 bit mode for HS200. */ + uint8_t tuningBlk8bit[] = { + 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCC, 0xCC, + 0xCC, 0x33, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0xCC, 0xFF, 0xFF, + 0xFF, 0xEE, 0xFF, 0xFF, 0xFF, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xDD, 0xFF, + 0xFF, 0xFF, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xBB, 0xFF, 0xFF, 0xFF, 0xBB, + 0xBB, 0xFF, 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF, 0x77, 0x77, 0xFF, 0x77, + 0xBB, 0xDD, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, + 0x00, 0xFF, 0xFF, 0xCC, 0xCC, 0xCC, 0x33, 0xCC, 0xCC, 0xCC, 0x33, 0x33, + 0xCC, 0xCC, 0xCC, 0xFF, 0xFF, 0xFF, 0xEE, 0xFF, 0xFF, 0xFF, 0xEE, 0xEE, + 0xFF, 0xFF, 0xFF, 0xDD, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, + 0xBB, 0xFF, 0xFF, 0xFF, 0xBB, 0xBB, 0xFF, 0xFF, 0xFF, 0x77, 0xFF, 0xFF, + 0xFF, 0x77, 0x77, 0xFF, 0x77, 0xBB, 0xDD, 0xEE, + }; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + cmd.cmdCode = cmdCode; + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_ADTC; + + if (cntlr->curDev->workPara.width == BUS_WIDTH4) { + data.blockSize = sizeof(tuningBlk4bit); + data.dataBuffer = tuningBlk4bit; + } else if (cntlr->curDev->workPara.width == BUS_WIDTH8) { + data.blockSize = sizeof(tuningBlk8bit); + data.dataBuffer = tuningBlk8bit; + } else { + HDF_LOGE("MmcSendTuning: work width is 1, can not tune!"); + return HDF_FAILURE; + } + data.blockNum = 1; + data.dataFlags = DATA_READ; + if (sendStop == true) { + data.sendStopCmd = true; + data.stopCmd.cmdCode = STOP_TRANSMISSION; + data.stopCmd.respType = MMC_RESP_R1B | MMC_CMD_TYPE_AC; + } + + return MmcSendCmd(cntlr, &cmd, &data, 1); +} + +static int32_t MmcSendEraseStartCmd(struct MmcCntlr *cntlr, uint32_t arg) +{ + struct MmcCmd cmd = {0}; + struct MmcDevice *dev = cntlr->curDev; + + if (dev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + /* SD: CMD32; EMMC: CMD35 */ + if (dev->type == MMC_DEV_SD) { + cmd.cmdCode = SD_CMD_ERASE_WR_BLK_START; + } else { + cmd.cmdCode = ERASE_GROUP_START; + } + /* [31:0]data address. */ + cmd.argument = arg; + /* + * Data address for media =<2GB is a 32bit byte address and data address for media > 2GB is + * a 32bit sector (512B) address. + */ + if (dev->state.bits.blockAddr == 0) { + cmd.argument <<= MMC_MAX_BLOCKSIZE_SHIFT; + } + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_AC; + return MmcSendCmd(cntlr, &cmd, NULL, 1); +} + +static int32_t MmcSendEraseEndCmd(struct MmcCntlr *cntlr, uint32_t arg) +{ + struct MmcCmd cmd = {0}; + struct MmcDevice *dev = cntlr->curDev; + + if (dev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + /* SD: CMD33; EMMC: CMD36 */ + if (dev->type == MMC_DEV_SD) { + cmd.cmdCode = SD_CMD_ERASE_WR_BLK_END; + } else { + cmd.cmdCode = ERASE_GROUP_END; + } + /* [31:0]data address. */ + cmd.argument = arg; + /* + * Data address for media =<2GB is a 32bit byte address and data address for media > 2GB is + * a 32bit sector (512B) address. + */ + if (dev->state.bits.blockAddr == 0) { + cmd.argument <<= MMC_MAX_BLOCKSIZE_SHIFT; + } + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_AC; + return MmcSendCmd(cntlr, &cmd, NULL, 1); +} + +static int32_t MmcSendEraseCmd(struct MmcCntlr *cntlr, uint32_t arg) +{ + struct MmcCmd cmd = {0}; + struct MmcDevice *dev = cntlr->curDev; + + if (dev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + /* ERASE cmd38 */ + cmd.cmdCode = MMC_ERASE; + cmd.argument = arg; + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_AC; + return MmcSendCmd(cntlr, &cmd, NULL, 1); +} + +static int32_t MmcAlignEraseSize(struct MmcCntlr *cntlr, uint32_t *start, uint32_t *end, uint32_t size) +{ + uint32_t curSize = size; + uint32_t tmp; + + if (cntlr->curDev->eraseSize == 0) { + return HDF_ERR_NOT_SUPPORT; + } + + /* align start. */ + tmp = (*start) % cntlr->curDev->eraseSize; + if (tmp > 0) { + tmp = cntlr->curDev->eraseSize - tmp; + (*start) += tmp; + if (curSize > tmp) { + curSize -= tmp; + } else { + return HDF_ERR_NOT_SUPPORT; + } + } + + /* align size. */ + tmp = curSize % cntlr->curDev->eraseSize; + if (tmp > 0) { + curSize -= tmp; + } + if (curSize == 0) { + return HDF_ERR_NOT_SUPPORT; + } + + (*end) = (*start) + curSize; + return HDF_SUCCESS; +} + +int32_t MmcSendErase(struct MmcCntlr *cntlr, uint32_t startSec, uint32_t nSec) +{ + int32_t ret; + uint32_t start = startSec; + uint32_t end = start + nSec; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + if (cntlr->curDev->eraseSize == 0 || + (cntlr->curDev->reg.csd.ccc & MMC_CSD_CCC_ERASE) == 0) { + return HDF_ERR_NOT_SUPPORT; + } + + ret = MmcAlignEraseSize(cntlr, &start, &end, nSec); + if (ret != HDF_SUCCESS) { + /* after align, no need to erase. */ + return HDF_SUCCESS; + } + + /* + * emmc: + * Starting the erase process is a three steps sequence. + * First the host defines the start address of the range using the ERASE_GROUP_START (CMD35) command, + * next it defines the last address of the range using the ERASE_GROUP_END (CMD36) command and + * finally it starts the erase process by issuing the ERASE (CMD38) command with argument bits set to zero. + * sd: + * The host should adhere to the following command sequence: ERASE_WR_BLK_START(cmd32), ERASE_WR_BLK_END(cmd33) + * and ERASE(CMD38). + */ + ret = MmcSendEraseStartCmd(cntlr, start); + if (ret != HDF_SUCCESS) { + HDF_LOGE("send erase start cmd fail, err = %d!", ret); + return ret; + } + + ret = MmcSendEraseEndCmd(cntlr, end); + if (ret != HDF_SUCCESS) { + HDF_LOGE("send erase end cmd fail, err = %d!", ret); + return ret; + } + + ret = MmcSendEraseCmd(cntlr, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("send erase cmd fail, err = %d!", ret); + return ret; + } + + return MmcWaitCardReady(cntlr); +} + +void MmcSetupReadWriteBlocksCmd(struct MmcDevice *mmc, struct MmcCmd *cmd, struct MmcRwData *info) +{ + cmd->data->blockSize = BYTES_PER_BLOCK; + cmd->data->blockNum = info->sectors; + cmd->data->dataBuffer = info->buf; + + cmd->respType = MMC_RESP_R1 | MMC_CMD_TYPE_ADTC; + /* [31:0]data address. */ + cmd->argument = info->startSector; + if (mmc->state.bits.blockAddr == 0) { + /* SDSC Card uses byte unit address and SDHC and SDXC Cards use block unit address(512 Bytes unit). */ + cmd->argument <<= MMC_MAX_BLOCKSIZE_SHIFT; + } + if (info->writeFlag == true) { + cmd->data->dataFlags = DATA_WRITE; + cmd->cmdCode = WRITE_BLOCK; + if (info->sectors > 1) { + cmd->cmdCode = WRITE_MULTIPLE_BLOCK; + } + } else { + cmd->data->dataFlags = DATA_READ; + cmd->cmdCode = READ_SINGLE_BLOCK; + if (info->sectors > 1) { + cmd->cmdCode = READ_MULTIPLE_BLOCK; + } + } + if ((info->sectors > 1) && (mmc->cntlr->caps.bits.cmdStop > 0)) { + cmd->data->stopCmd.cmdCode = STOP_TRANSMISSION; + cmd->data->sendStopCmd = true; + } +} + +int32_t MmcSendReadWriteBlocks(struct MmcCntlr *cntlr, struct MmcRwData *info) +{ + struct MmcCmd cmd = {0}; + struct MmcData data = {0}; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + cmd.data = &data; + MmcSetupReadWriteBlocksCmd(cntlr->curDev, &cmd, info); + return MmcSendCmd(cntlr, &cmd, &data, 1); +} + +static int32_t EmmcDecodeCsd(struct MmcCntlr *cntlr) +{ + struct MmcCsd *csd = NULL; + uint32_t unit, factor; + uint32_t *rawCsd = NULL; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + rawCsd = cntlr->curDev->reg.rawCsd; + csd = &(cntlr->curDev->reg.csd); + + /* CSD_STRUCTURE: [127:126]. */ + csd->structure = MmcParseBits(rawCsd, CSD_BITS, 126, 2); + if (csd->structure == 0) { + HDF_LOGE("EmmcDecodeCsd: structure is invalid!"); + return HDF_ERR_INVALID_PARAM; + } + + /* SPEC_VERS: [125:122]. */ + csd->specVers = MmcParseBits(rawCsd, CSD_BITS, 122, 4); + /* TAAC: [119:112]; TAAC bit position-->Time unit: [2:0], Multiplier factor: [6:3]. */ + factor = MmcParseBits(rawCsd, CSD_BITS, 115, 4); + unit = MmcParseBits(rawCsd, CSD_BITS, 112, 3); + csd->taccNs = (g_taccUnit[unit] * g_commFactor[factor] + 9) / 10; + /* NSAC: [111:104] */ + csd->taccClks = MmcParseBits(rawCsd, CSD_BITS, 104, 8) * 100; + + /* TRAN_SPEED: [103:96]; TRAN_SPEED bit-->Frequency unit: [2:0], Multiplier factor: [6:3]. */ + factor = MmcParseBits(rawCsd, CSD_BITS, 99, 4); + unit = MmcParseBits(rawCsd, CSD_BITS, 96, 3); + csd->maxDtr = g_tranSpeedUnit[unit] * g_commFactor[factor]; + csd->ccc = MmcParseBits(rawCsd, CSD_BITS, 84, 12); + + /* C_SIZE: [73:62] */ + factor = MmcParseBits(rawCsd, CSD_BITS, 62, 12); + /* C_SIZE_MULT: [49:47] */ + unit = MmcParseBits(rawCsd, CSD_BITS, 47, 3); + csd->capacity = (1 + factor) << (unit + 2); + /* READ_BL_LEN: [83:80]. */ + csd->readBlkLen = MmcParseBits(rawCsd, CSD_BITS, 80, 4); + /* READ_BL_PARTIAL: [79:79] */ + csd->rdPartial = MmcParseBits(rawCsd, CSD_BITS, 79, 1); + /* WRITE_BLK_MISALIGN: [78:78] */ + csd->wrMisalign = MmcParseBits(rawCsd, CSD_BITS, 78, 1); + /* READ_BLK_MISALIGN: [77:77] */ + csd->rdMisalign = MmcParseBits(rawCsd, CSD_BITS, 77, 1); + /* Write speed factor(R2W_FACTOR) :[28:26] */ + csd->r2wFactor = MmcParseBits(rawCsd, CSD_BITS, 26, 3); + /* WRITE_BL_LEN: [25:22] */ + csd->writeBlkLen = MmcParseBits(rawCsd, CSD_BITS, 22, 4); + /* WRITE_BL_PARTIAL: [21:21] */ + csd->wrPartial = MmcParseBits(rawCsd, CSD_BITS, 21, 1); + + /* + * Note that the support for 512B read access is mandatory for all cards. + * And that the cards has to be in 512B block length mode by default after power-on, or software reset. + */ + if (csd->writeBlkLen >= MMC_MAX_BLOCKSIZE_SHIFT) { + /* ERASE_GRP_SIZE: [46:42] */ + unit = MmcParseBits(rawCsd, CSD_BITS, 42, 5); + /* ERASE_GRP_MULT: [41:37] */ + factor = MmcParseBits(rawCsd, CSD_BITS, 37, 5); + /* size of erasable unit = (ERASE_GRP_SIZE + 1) * (ERASE_GRP_MULT + 1) */ + csd->eraseSize = (unit + 1) * (factor + 1); + csd->eraseSize <<= (csd->writeBlkLen - MMC_MAX_BLOCKSIZE_SHIFT); + } + return HDF_SUCCESS; +} + +static int32_t EmmcDecodeCid(struct MmcCntlr *cntlr) +{ + uint32_t i; + struct MmcCid *cid = NULL; + uint32_t *rawCid = NULL; + uint8_t specVers, cbx; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + rawCid = cntlr->curDev->reg.rawCid; + cid = &(cntlr->curDev->reg.cid); + specVers = cntlr->curDev->reg.csd.specVers; + if (specVers > MMC_CSD_SPEC_VER_4) { + HDF_LOGE("EmmcDecodeCid: specVers is invalid!"); + return HDF_ERR_NOT_SUPPORT; + } + + /* + * The manufacturing date is composed of two hexadecimal digits, four bits each, + * representing a two digits date code m/y; + */ + cid->month = MmcParseBits(rawCid, CID_BITS, 12, 4); + /* The "y" field, least significant nibble, is the year code. 0 is 1997. */ + cid->year = MmcParseBits(rawCid, CID_BITS, 8, 4) + 1997; + + if (specVers == MMC_CSD_SPEC_VER_0 || specVers == MMC_CSD_SPEC_VER_1) { + cid->mid = MmcParseBits(rawCid, CID_BITS, 104, 24); + for (i = 0; i < 7; i++) { + cid->pnm[i] = MmcParseBits(rawCid, CID_BITS, 96 - (i * 8), 8); + } + cid->pnm[7] = '\0'; + cid->hwPrv = MmcParseBits(rawCid, CID_BITS, 44, 4); + cid->fwPrv = MmcParseBits(rawCid, CID_BITS, 40, 4); + cid->psn = MmcParseBits(rawCid, CID_BITS, 16, 24); + } else { + /* Manufacturer ID(MID): [127:120] */ + cid->mid = MmcParseBits(rawCid, CID_BITS, 120, 8); + /* OEM/Application ID(OID): [119:104] */ + cid->oid = MmcParseBits(rawCid, CID_BITS, 104, 16); + /* Product name(PNM): [103:56] */ + for (i = 0; i < 6; i++) { + cid->pnm[i] = MmcParseBits(rawCid, CID_BITS, 96 - (i * 8), 8); + } + cid->pnm[6] = '\0'; + /* Product serial number(PSN): [47:16] */ + cid->psn = MmcParseBits(rawCid, CID_BITS, 16, 32); + /* + * Card or BGA(CBX): [113:112] + * 00: Card (removable); 01: BGA (Discrete embedded); 10: POP; 11: Reserved. + */ + cbx = MmcParseBits(rawCid, CID_BITS, 112, 2); + if (cbx == 0) { + cntlr->curDev->state.bits.removeable = 1; + HDF_LOGD("Emmc is removeable!"); + } + } + return HDF_SUCCESS; +} + +static void EmmcDecodeExtCsdSector(struct EmmcDevice *emmcDev, struct EmmcExtCsd *extCsd) +{ + uint32_t i; + uint32_t shift = 0; + + extCsd->sectors = 0; + for (i = 0; i < EMMC_EXT_CSD_SEC_CNT_BYTES; i++) { + extCsd->sectors |= (uint32_t)(extCsd->rawSectors[i] << shift); + shift += BITS_PER_BYTE; + } + /* Device density > 2GiB are sector addressed. */ + if (extCsd->sectors > (2u * 1024 * 1024 * 1024) / 512) { + emmcDev->mmc.state.bits.blockAddr = 1; + } +} + +static void EmmcDecodeExtCsdCardType(struct EmmcExtCsd *extCsd) +{ + uint8_t cardType = extCsd->rawCardType & EMMC_EXT_CSD_CARD_TYPE_MASK; + + switch (cardType) { + case EMMC_EXT_CSD_CARD_TYPE_SDR_ALL: + case EMMC_EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V: + case EMMC_EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V: + case EMMC_EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52: + extCsd->hsMaxDtr = EMMC_EXT_CSD_HIGH_SPEED_200; + extCsd->cardType = EMMC_EXT_CSD_CARD_TYPE_SDR_200; + break; + case EMMC_EXT_CSD_CARD_TYPE_SDR_1_2V_ALL: + case EMMC_EXT_CSD_CARD_TYPE_SDR_1_2V_ALL_DDR_1_8V: + case EMMC_EXT_CSD_CARD_TYPE_SDR_1_2V_ALL_DDR_1_2V: + case EMMC_EXT_CSD_CARD_TYPE_SDR_1_2V_ALL_DDR_52: + extCsd->hsMaxDtr = EMMC_EXT_CSD_HIGH_SPEED_200; + extCsd->cardType = EMMC_EXT_CSD_CARD_TYPE_SDR_1_2V; + break; + case EMMC_EXT_CSD_CARD_TYPE_SDR_1_8V_ALL: + case EMMC_EXT_CSD_CARD_TYPE_SDR_1_8V_ALL_DDR_1_8V: + case EMMC_EXT_CSD_CARD_TYPE_SDR_1_8V_ALL_DDR_1_2V: + case EMMC_EXT_CSD_CARD_TYPE_SDR_1_8V_ALL_DDR_52: + extCsd->hsMaxDtr = EMMC_EXT_CSD_HIGH_SPEED_200; + extCsd->cardType = EMMC_EXT_CSD_CARD_TYPE_SDR_1_8V; + break; + case (EMMC_EXT_CSD_CARD_TYPE_DDR_52 | EMMC_EXT_CSD_CARD_TYPE_52 | EMMC_EXT_CSD_CARD_TYPE_26): + extCsd->hsMaxDtr = EMMC_EXT_CSD_HIGH_SPEED_52; + extCsd->cardType = EMMC_EXT_CSD_CARD_TYPE_DDR_52; + break; + case (EMMC_EXT_CSD_CARD_TYPE_DDR_1_2V | EMMC_EXT_CSD_CARD_TYPE_52 | EMMC_EXT_CSD_CARD_TYPE_26): + extCsd->hsMaxDtr = EMMC_EXT_CSD_HIGH_SPEED_52; + extCsd->cardType = EMMC_EXT_CSD_CARD_TYPE_DDR_1_2V; + break; + case (EMMC_EXT_CSD_CARD_TYPE_DDR_1_8V | EMMC_EXT_CSD_CARD_TYPE_52 | EMMC_EXT_CSD_CARD_TYPE_26): + extCsd->hsMaxDtr = EMMC_EXT_CSD_HIGH_SPEED_52; + extCsd->cardType = EMMC_EXT_CSD_CARD_TYPE_DDR_1_8V; + break; + case (EMMC_EXT_CSD_CARD_TYPE_52 | EMMC_EXT_CSD_CARD_TYPE_26): + extCsd->hsMaxDtr = EMMC_EXT_CSD_HIGH_SPEED_52; + break; + case EMMC_EXT_CSD_CARD_TYPE_26: + extCsd->hsMaxDtr = EMMC_EXT_CSD_HIGH_SPEED_26; + break; + default: + HDF_LOGD("EmmcDecodeExtCsdCardType: not support high-speed!"); + break; + } +} + +static void EmmcDecodeExtCsdRev13Field(struct EmmcExtCsd *extCsd, uint8_t *rawExtCsd) +{ + uint8_t shift = rawExtCsd[EMMC_EXT_CSD_S_A_TIMEOUT]; + + extCsd->eraseGroupDef = rawExtCsd[EMMC_EXT_CSD_ERASE_GROUP_DEF]; + extCsd->partConfig = rawExtCsd[EMMC_EXT_CSD_PARTITION_CONFIG]; + extCsd->partSwitchTime = 10 * rawExtCsd[EMMC_EXT_CSD_PARTITION_SWITCH_TIME]; + + if (shift > 0 && shift <= MAX_S_A_TIMEOUT_VALUE) { + extCsd->saTimeout = 1 << shift; + } + extCsd->relWrSecorCount = rawExtCsd[EMMC_EXT_CSD_REL_WR_SEC_C]; + extCsd->hcEraseTimeout = 300 * rawExtCsd[EMMC_EXT_CSD_ERASE_TIMEOUT_MULT]; + extCsd->hcEraseSize = (extCsd->rawHcEraseGrpSize) << 10; + extCsd->bootSize = rawExtCsd[EMMC_EXT_CSD_BOOT_MULTI] << 17; +} + +static void EmmcDecodeExtCsdEnhanceArea(struct EmmcDevice *emmcDev, + struct EmmcExtCsd *extCsd, uint8_t *rawExtCsd) +{ + uint32_t i; + uint32_t shift = 0; + + extCsd->enhAreaEnable = true; + extCsd->enhAreaOffset = 0; + for (i = 0; i < EMMC_EXT_CSD_ENH_START_ADDR_BYTES; i++) { + extCsd->enhAreaOffset |= ((uint64_t)rawExtCsd[EMMC_EXT_CSD_ENH_START_ADDR + i] << shift); + shift += BITS_PER_BYTE; + } + /* + * Start address of the Enhanced User Data Area segment in the User Data Area + * (expressedin bytes or in sectors in case of high capacity devices). + */ + if (emmcDev->mmc.state.bits.blockAddr == 1) { + extCsd->enhAreaOffset <<= MMC_MAX_BLOCKSIZE_SHIFT; + } + + shift = 0; + extCsd->enhAreaSize = 0; + for (i = 0; i < EMMC_EXT_CSD_ENH_SIZE_MULT_BYTES; i++) { + extCsd->enhAreaSize |= (rawExtCsd[EMMC_EXT_CSD_ENH_SIZE_MULT + i] << shift); + shift += BITS_PER_BYTE; + } + /* Max Enhanced Area = MAX_ENH_SIZE_MULT * HC_WP_GRP_SIZE * HC_ERASE_GPR_SIZE * 512kBytes */ + extCsd->enhAreaSize *= (uint32_t)(extCsd->rawHcEraseGrpSize * rawExtCsd[EMMC_EXT_CSD_HC_WP_GRP_SIZE]); + extCsd->enhAreaSize <<= MMC_MAX_BLOCKSIZE_SHIFT; +} + +static void EmmcDecodeExtCsdPowerClassValue(struct EmmcExtCsd *extCsd, uint8_t *rawExtCsd) +{ + extCsd->pwrClF52V195 = rawExtCsd[EMMC_EXT_CSD_PWR_CL_52_195]; + extCsd->pwrClF26V195 = rawExtCsd[EMMC_EXT_CSD_PWR_CL_26_195]; + extCsd->pwrClF52V360 = rawExtCsd[EMMC_EXT_CSD_PWR_CL_52_360]; + extCsd->pwrClF26V360 = rawExtCsd[EMMC_EXT_CSD_PWR_CL_26_360]; + extCsd->pwrClF200V195 = rawExtCsd[EMMC_EXT_CSD_PWR_CL_200_195]; + extCsd->pwrClF200V360 = rawExtCsd[EMMC_EXT_CSD_PWR_CL_200_360]; + extCsd->pwrClDdrF52V195 = rawExtCsd[EMMC_EXT_CSD_PWR_CL_DDR_52_195]; + extCsd->pwrClDdrF52V360 = rawExtCsd[EMMC_EXT_CSD_PWR_CL_DDR_52_360]; +} + +static void EmmcDecodeExtCsdRev14Field(struct EmmcDevice *emmcDev, + struct EmmcExtCsd *extCsd, uint8_t *rawExtCsd) +{ + if ((rawExtCsd[EMMC_EXT_CSD_PARTITIONING_SUPPORT] & PARTITIONING_SUPPORT_ENH_ATTRIBUTE_EN) > 0 && + (rawExtCsd[EMMC_EXT_CSD_PARTITIONS_ATTRIBUTE] & PARTITIONS_ATTRIBUTE_ENH_USR) > 0) { + EmmcDecodeExtCsdEnhanceArea(emmcDev, extCsd, rawExtCsd); + } + extCsd->secTrimMult = extCsd->rawSecTrimMult; + extCsd->secEraseMult = extCsd->rawSecEraseMult; + /* TRIM Timeout = 300ms x TRIM_MULT. */ + extCsd->trimTimeout = 300 * extCsd->rawTrimMult; + EmmcDecodeExtCsdPowerClassValue(extCsd, rawExtCsd); +} + +static void EmmcDecodeExtCsdRev15Field(struct EmmcExtCsd *extCsd, uint8_t *rawExtCsd) +{ + /* whether the eMMC card supports HPI. */ + if ((rawExtCsd[EMMC_EXT_CSD_HPI_FEATURES] & EMMC_EXT_CSD_HPI_SUPPORT) > 0) { + extCsd->hpi = true; + if ((rawExtCsd[EMMC_EXT_CSD_HPI_FEATURES] & EMMC_EXT_CSD_HPI_IMPLEMENTATION) > 0) { + extCsd->hpiCmd = STOP_TRANSMISSION; + } else { + extCsd->hpiCmd = SEND_STATUS; + } + /* + * This field indicates the maximum timeout to close a command interrupted by HPI –time between the end + * bit of CMD12/13 to the DAT0 release by the device. + * Time is expressed in units of 10-milliseconds. + */ + extCsd->outOfInterruptTime = rawExtCsd[EMMC_EXT_CSD_OUT_OF_INTERRUPT_TIME] * 10; + } + extCsd->wrRelParam = rawExtCsd[EMMC_EXT_CSD_WR_REL_PARAM]; +} + +static int32_t EmmcDecodeExtCsd(struct MmcCntlr *cntlr, uint8_t *rawExtCsd, uint32_t len) +{ + struct EmmcDevice *emmcDev = (struct EmmcDevice *)cntlr->curDev; + struct EmmcExtCsd *extCsd = &(emmcDev->emmcReg.extCsd); + uint32_t i; + + extCsd->rawCsdStructure = rawExtCsd[EMMC_EXT_CSD_STRUCTURE]; + if (emmcDev->mmc.reg.csd.structure == MMC_CSD_STRUCTURE_VER_OTHER) { + if (extCsd->rawCsdStructure > EMMC_EXT_CSD_STRUCTURE_VER_1_2) { + HDF_LOGE("EmmcDecodeExtCsd: rawCsdStructure is invalid!"); + return HDF_ERR_INVALID_PARAM; + } + } + extCsd->rev = rawExtCsd[EMMC_EXT_CSD_REV]; + for (i = 0; i < EMMC_EXT_CSD_SEC_CNT_BYTES; i++) { + extCsd->rawSectors[i] = rawExtCsd[EMMC_EXT_CSD_SEC_CNT + i]; + } + if (extCsd->rev >= EMMC_EXT_CSD_REV_1_2) { + EmmcDecodeExtCsdSector(emmcDev, extCsd); + } + + extCsd->strobeSupport = rawExtCsd[EMMC_EXT_CSD_STROBE_SUPPORT]; + extCsd->rawCardType = rawExtCsd[EMMC_EXT_CSD_CARD_TYPE]; + EmmcDecodeExtCsdCardType(extCsd); + + extCsd->rawSaTimeout = rawExtCsd[EMMC_EXT_CSD_S_A_TIMEOUT]; + extCsd->rawEraseTimeoutMult = rawExtCsd[EMMC_EXT_CSD_ERASE_TIMEOUT_MULT]; + extCsd->rawHcEraseGrpSize = rawExtCsd[EMMC_EXT_CSD_HC_ERASE_GRP_SIZE]; + if (extCsd->rev >= EMMC_EXT_CSD_REV_1_3) { + EmmcDecodeExtCsdRev13Field(extCsd, rawExtCsd); + } + + extCsd->rawSecTrimMult = rawExtCsd[EMMC_EXT_CSD_SEC_TRIM_MULT]; + extCsd->rawSecEraseMult = rawExtCsd[EMMC_EXT_CSD_SEC_ERASE_MULT]; + extCsd->rawSecFeatureSupport = rawExtCsd[EMMC_EXT_CSD_SEC_FEATURE_SUPPORT]; + extCsd->rawTrimMult = rawExtCsd[EMMC_EXT_CSD_TRIM_MULT]; + if (extCsd->rev >= EMMC_EXT_CSD_REV_1_4) { + EmmcDecodeExtCsdRev14Field(emmcDev, extCsd, rawExtCsd); + } + + if (extCsd->rev >= EMMC_EXT_CSD_REV_1_5) { + EmmcDecodeExtCsdRev15Field(extCsd, rawExtCsd); + } + return HDF_SUCCESS; +} + +static void EmmcSetBlockCapacity(struct MmcCntlr *cntlr) +{ + struct EmmcDevice *emmcDev = (struct EmmcDevice *)cntlr->curDev; + uint32_t gibVal, mibVal; + + /* + * ERASE_GROUP_DEF Bit0: ENABLE: + * 0x0 : Use old erase group size and write protect group size definition (default) + * 0x1 : Use high-capacity erase unit size, high capacity erase timeout, and high-capacity write protect + * group size definition. + */ + if (emmcDev->emmcReg.extCsd.eraseGroupDef == 1) { + emmcDev->mmc.eraseSize = emmcDev->emmcReg.extCsd.hcEraseSize; + } else { + emmcDev->mmc.eraseSize = emmcDev->mmc.reg.csd.eraseSize; + } + + if (emmcDev->mmc.state.bits.blockAddr > 0) { + emmcDev->mmc.capacity = emmcDev->emmcReg.extCsd.sectors; + } else { + emmcDev->mmc.capacity = (size_t)emmcDev->mmc.reg.csd.capacity << + (emmcDev->mmc.reg.csd.readBlkLen - MMC_MAX_BLOCKSIZE_SHIFT); + } + + gibVal = emmcDev->mmc.capacity >> 21; + mibVal = (emmcDev->mmc.capacity & ~(gibVal << 21)) >> 11; + HDF_LOGD("Emmc dev capacity %d.%d Gib", gibVal, mibVal); +} + +static int32_t EmmcCheckExtCsd(struct MmcCntlr *cntlr, enum MmcBusWidth width) +{ + uint8_t extCsd[EXT_CSD_BYTES_LEN] = {0}; + + if (width == BUS_WIDTH1) { + return 0; + } + + return MmcSendExtCsd(cntlr, extCsd, EXT_CSD_BYTES_LEN); +} + +static int32_t EmmcSwitchVoltage(struct MmcCntlr *cntlr, struct EmmcDevice *emmcDev) +{ + uint32_t cardType = emmcDev->emmcReg.extCsd.cardType; + + /* Host Voltage Switch. */ + if (cntlr->caps2.bits.hs200Sdr1v2 == 1 && (cardType & EMMC_EXT_CSD_CARD_TYPE_SDR_1_2V) > 0) { + (void)MmcCntlrSwitchVoltage(cntlr, VOLT_1V2); + } + if (cntlr->caps2.bits.hs200Sdr1v8 && (cardType & EMMC_EXT_CSD_CARD_TYPE_SDR_1_8V) > 0) { + (void)MmcCntlrSwitchVoltage(cntlr, VOLT_1V8); + } + return HDF_SUCCESS; +} + +static int32_t EmmcSelectHighSpeedBusWidth(struct MmcCntlr *cntlr) +{ + int err = HDF_FAILURE; + enum MmcBusWidth width = BUS_WIDTH1; + + if (cntlr->caps.bits.cap8Bit > 0) { + err = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_BUS_WIDTH, EMMC_EXT_CSD_BUS_WIDTH_8); + if (err != HDF_SUCCESS) { + HDF_LOGD("EmmcSelectHighSpeedBusWidth: switch 8 bit bus width fail!"); + } else { + MmcCntlrSetBusWidth(cntlr, BUS_WIDTH8); + width = BUS_WIDTH8; + } + } + if (err != HDF_SUCCESS) { + err = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_BUS_WIDTH, EMMC_EXT_CSD_BUS_WIDTH_4); + if (err != HDF_SUCCESS) { + HDF_LOGD("EmmcSelectHighSpeedBusWidth: switch 4 bit bus width fail!"); + } else { + MmcCntlrSetBusWidth(cntlr, BUS_WIDTH4); + width = BUS_WIDTH4; + } + } + if (err != HDF_SUCCESS) { + return err; + } + + return EmmcCheckExtCsd(cntlr, width); +} + +static int32_t EmmcCheckSwitchStatus(struct MmcCntlr *cntlr) +{ + int err; + uint32_t status; + + err = MmcSendStatus(cntlr, &status); + if (err != HDF_SUCCESS) { + HDF_LOGE("EmmcCheckSwitchStatus: send status cmd fail!"); + return err; + } + if ((status & SWITCH_ERROR) > 0) { + return HDF_MMC_ERR_SWITCH_FAIL; + } + return HDF_SUCCESS; +} + +static int32_t EmmcSwitchHighSpeed(struct MmcCntlr *cntlr) +{ + int err; + + /* + * Switch dev to HS mode. + * HS_TIMING must be set to "0x1" before setting BUS_WIDTH for dual data rate operation (values 5 or 6). + */ + err = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_HS_TIMING, EMMC_EXT_CSD_BUS_TIMING_HS); + if (err != HDF_SUCCESS) { + HDF_LOGE("EmmcSwitchHighSpeed: switch hs fail!"); + return err; + } + /* change host freq to 52M according to JEDEC Standard No.84-B51, Page49. */ + MmcCntlrSetClock(cntlr, EMMC_EXT_CSD_HIGH_SPEED_52); + /* Set host controller to HS timing. */ + MmcCntlrSetBusTiming(cntlr, BUS_TIMING_MMC_HS); + return HDF_SUCCESS; +} + +static int32_t EmmcSelectHs400(struct MmcCntlr *cntlr) +{ + int err; + + err = EmmcSwitchHighSpeed(cntlr); + if (err != HDF_SUCCESS) { + HDF_LOGE("EmmcSelectHs400: switch hs fail!"); + return err; + } + + /* Switch dev to DDR. */ + err = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_BUS_WIDTH, EMMC_EXT_CSD_DDR_BUS_WIDTH_8); + if (err != HDF_SUCCESS) { + HDF_LOGE("EmmcSelectHs400: switch to ddr fail!"); + return err; + } + /* Switch dev to HS400. */ + err = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_HS_TIMING, EMMC_EXT_CSD_BUS_TIMING_HS400); + if (err != HDF_SUCCESS) { + HDF_LOGE("EmmcSelectHs400: switch to hs400 fail!"); + return err; + } + MmcCntlrSetClock(cntlr, EMMC_EXT_CSD_HIGH_SPEED_200); + /* Set host controller to HS400 timing and frequency. */ + MmcCntlrSetBusTiming(cntlr, BUS_TIMING_MMC_HS400); + return EmmcCheckSwitchStatus(cntlr); +} + +static int32_t EmmcSelectHs400es(struct MmcCntlr *cntlr, struct EmmcDevice *emmcDev) +{ + int err; + + err = EmmcSwitchVoltage(cntlr, emmcDev); + if (err != HDF_SUCCESS) { + return err; + } + + err = EmmcSelectHighSpeedBusWidth(cntlr); + if (err != HDF_SUCCESS) { + HDF_LOGE("EmmcSelectHs400es: select hs width fail!"); + return err; + } + + err = EmmcSwitchHighSpeed(cntlr); + if (err != HDF_SUCCESS) { + HDF_LOGE("EmmcSelectHs400es: switch hs fail!"); + return err; + } + + /* Switch dev to DDR with strobe bit. */ + err = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_BUS_WIDTH, + EMMC_EXT_CSD_DDR_BUS_WIDTH_8 | EMMC_EXT_CSD_BUS_WIDTH_STROBE); + if (err != HDF_SUCCESS) { + HDF_LOGE("EmmcSelectHs400es: switch to ddr fail!"); + return err; + } + /* Switch dev to HS400. */ + err = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_HS_TIMING, EMMC_EXT_CSD_BUS_TIMING_HS400); + if (err != HDF_SUCCESS) { + HDF_LOGE("EmmcSelectHs400es: switch to hs400 fail!"); + return err; + } + MmcCntlrSetClock(cntlr, EMMC_EXT_CSD_HIGH_SPEED_200); + /* Set host controller to HS400 timing and frequency. */ + MmcCntlrSetBusTiming(cntlr, BUS_TIMING_MMC_HS400); + MmcCntlrSetEnhanceSrobe(cntlr, true); + return EmmcCheckSwitchStatus(cntlr); +} + +static int32_t EmmcSelectHs200(struct MmcCntlr *cntlr, struct EmmcDevice *emmcDev) +{ + int err; + + err = EmmcSwitchVoltage(cntlr, emmcDev); + if (err != HDF_SUCCESS) { + return err; + } + + err = EmmcSelectHighSpeedBusWidth(cntlr); + if (err != HDF_SUCCESS) { + HDF_LOGE("EmmcSelectHs200: select hs width fail!"); + return err; + } + + /* Switch dev to HS200. */ + err = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_HS_TIMING, EMMC_EXT_CSD_BUS_TIMING_HS200); + if (err != HDF_SUCCESS) { + HDF_LOGE("EmmcSelectHs200: switch to hs200 fail!"); + return err; + } + MmcCntlrSetBusTiming(cntlr, BUS_TIMING_MMC_HS200); + return EmmcCheckSwitchStatus(cntlr); +} + +static uint32_t EmmcGetPowerClassValue(struct MmcCntlr *cntlr, struct EmmcExtCsd *extCsd) +{ + uint32_t val = 0; + uint32_t vdd, busWidthBit, clock; + + busWidthBit = (cntlr->curDev->workPara.width == BUS_WIDTH8) ? + EMMC_EXT_CSD_BUS_WIDTH_8 : EMMC_EXT_CSD_BUS_WIDTH_4; + vdd = 1 << (cntlr->vddBit); + clock = cntlr->curDev->workPara.clock; + + if (vdd == MMC_OCR_1V65_1V95) { + if (clock <= EMMC_EXT_CSD_HIGH_SPEED_26) { + val = extCsd->pwrClF26V195; + } else if (clock <= EMMC_EXT_CSD_HIGH_SPEED_52) { + val = extCsd->pwrClF52V195; + } else if (clock <= EMMC_EXT_CSD_HIGH_SPEED_200) { + val = extCsd->pwrClF200V195; + } + } else if (vdd >= MMC_OCR_2V7_2V8 && vdd <= MMC_OCR_3V5_3V6) { + if (clock <= EMMC_EXT_CSD_HIGH_SPEED_26) { + val = extCsd->pwrClF26V360; + } else if (clock <= EMMC_EXT_CSD_HIGH_SPEED_52) { + val = extCsd->pwrClF52V360; + } else if (clock <= EMMC_EXT_CSD_HIGH_SPEED_200) { + val = extCsd->pwrClF200V360; + } + } else { + return 0; + } + + if (busWidthBit == EMMC_EXT_CSD_BUS_WIDTH_8) { + val = (val & EMMC_EXT_CSD_PWR_CL_8BIT_MASK) >> EMMC_EXT_CSD_PWR_CL_8BIT_SHIFT; + } else { + val = (val & EMMC_EXT_CSD_PWR_CL_4BIT_MASK) >> EMMC_EXT_CSD_PWR_CL_4BIT_SHIFT; + } + return val; +} + +static int32_t EmmcSelectPowerClass(struct MmcCntlr *cntlr, struct EmmcExtCsd *extCsd) +{ + int32_t error = 0; + uint32_t val; + + if (cntlr->curDev->reg.csd.specVers < MMC_CSD_SPEC_VER_4) { + return HDF_SUCCESS; + } + + val = EmmcGetPowerClassValue(cntlr, extCsd); + if (val > 0) { + error = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_POWER_CLASS, val); + } + return error; +} + +static int32_t EmmcSelectActivateHighSpeed(struct MmcCntlr *cntlr, + struct EmmcDevice *emmcDev, struct EmmcExtCsd *extCsd) +{ + int32_t error; + + if (extCsd->hsMaxDtr > 0) { + error = HDF_SUCCESS; + if (MmcCntlrSupportHighSpeed200(cntlr) == true && + extCsd->hsMaxDtr > EMMC_EXT_CSD_HIGH_SPEED_52) { + error = EmmcSelectHs200(cntlr, emmcDev); + if (error == HDF_SUCCESS) { + emmcDev->mmc.state.bits.hs200 = 1; + } + } else if (cntlr->caps.bits.highSpeed == 1) { + error = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_HS_TIMING, + EMMC_EXT_CSD_BUS_TIMING_HS); + if (error == HDF_SUCCESS) { + emmcDev->mmc.state.bits.highSpeed = 1; + MmcCntlrSetBusTiming(cntlr, BUS_TIMING_MMC_HS); + } + } + if (error != HDF_SUCCESS && error != HDF_MMC_ERR_SWITCH_FAIL) { + return error; + } + } + + return HDF_SUCCESS; +} + +static int32_t EmmcSelectBusSpeedMode(struct MmcCntlr *cntlr, struct EmmcDevice *emmcDev, struct EmmcExtCsd *extCsd) +{ + int32_t error; + + /* HS400ES mode requires 8-bit bus width. */ + if (extCsd->strobeSupport > 0 && MmcCntlrSupportHighSpeed400EnhancedStrobe(cntlr) == true) { + error = EmmcSelectHs400es(cntlr, emmcDev); + if (error != HDF_SUCCESS) { + return error; + } + emmcDev->mmc.state.bits.hs400es = 1; + } else { + /* Activate high speed if supported. */ + error = EmmcSelectActivateHighSpeed(cntlr, emmcDev, extCsd); + if (error != HDF_SUCCESS) { + return error; + } + /* host set clock. */ + if (emmcDev->mmc.state.bits.hs200 == 1 || emmcDev->mmc.state.bits.highSpeed == 1) { + if (extCsd->hsMaxDtr > 0) { + MmcCntlrSetClock(cntlr, extCsd->hsMaxDtr); + } + } else if (emmcDev->mmc.reg.csd.maxDtr > 0) { + MmcCntlrSetClock(cntlr, emmcDev->mmc.reg.csd.maxDtr); + } + } + + if (emmcDev->mmc.state.bits.hs400es == 1) { + error = EmmcSelectPowerClass(cntlr, extCsd); + if (error != HDF_SUCCESS) { + HDF_LOGD("EmmcSelectBusSpeedMode: hs400es select power class fail!"); + } + } else if (emmcDev->mmc.state.bits.hs200 == 1) { + if ((cntlr->caps2.bits.hs200Sdr1v8 | cntlr->caps2.bits.hs200Sdr1v2) > 0) { + error = MmcCntlrTune(cntlr, SEND_TUNING_BLOCK_HS200); + if (error != HDF_SUCCESS) { + return error; + } + } + + if ((extCsd->rawCardType & EMMC_EXT_CSD_CARD_TYPE_HS400) > 0 && + MmcCntlrSupportHighSpeed400(cntlr) == true) { + error = EmmcSelectHs400(cntlr); + if (error != HDF_SUCCESS) { + return error; + } + emmcDev->mmc.state.bits.hs400 = 1; + emmcDev->mmc.state.bits.hs200 = 0; + } + + error = EmmcSelectPowerClass(cntlr, extCsd); + if (error != HDF_SUCCESS) { + HDF_LOGD("EmmcSelectBusSpeedMode: hs200 select power class fail!"); + } + } + + return HDF_SUCCESS; +} + +static uint32_t EmmcGetDdrMode(struct MmcCntlr *cntlr, struct EmmcDevice *emmcDev, struct EmmcExtCsd *extCsd) +{ + uint32_t ddrMode = MMC_BUS_MODE_NULL; + + /* Indicate DDR mode (if supported). */ + if (emmcDev->mmc.state.bits.highSpeed == 1) { + if ((extCsd->cardType & EMMC_EXT_CSD_CARD_TYPE_DDR_1_8V) > 0 && + (cntlr->caps.bits.ddr1v8 > 0) && + (cntlr->caps.bits.uhsDdr50 > 0)) { + ddrMode = MMC_1_8V_DDR_MODE; + } else if ((extCsd->cardType & EMMC_EXT_CSD_CARD_TYPE_DDR_1_2V) > 0 && cntlr->caps.bits.ddr1v2 > 0) { + ddrMode = MMC_1_2V_DDR_MODE; + } + } + return ddrMode; +} + +static int32_t EmmcSwitchDdrMode(struct MmcCntlr *cntlr, uint32_t ddrMode, + enum MmcBusWidth width, uint32_t widthBit) +{ + int32_t error; + + error = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_BUS_WIDTH, widthBit); + if (error != HDF_SUCCESS) { + HDF_LOGE("EmmcSwitchDdrMode: switch BUS_WIDTH fail!"); + return error; + } + + if (ddrMode == MMC_1_2V_DDR_MODE) { + error = MmcCntlrSwitchVoltage(cntlr, VOLT_1V2); + if (error != HDF_SUCCESS) { + HDF_LOGE("EmmcSwitchDdrMode: switch 1.2V fail!"); + return error; + } + } + cntlr->curDev->state.bits.ddrMode = 1; + MmcCntlrSetBusTiming(cntlr, BUS_TIMING_UHS_DDR50); + MmcCntlrSetBusWidth(cntlr, width); + return HDF_SUCCESS; +} + +static int32_t EmmcSelectSwitchDdrMode(struct MmcCntlr *cntlr, struct EmmcDevice *emmcDev, + struct EmmcExtCsd *extCsd) +{ + int32_t error; + uint32_t index, ddrMode; + enum MmcBusWidth width; + enum MmcBusWidth busWidths[] = { BUS_WIDTH8, BUS_WIDTH4, BUS_WIDTH1 }; + uint32_t busWidthBit[][2] = { + { EMMC_EXT_CSD_BUS_WIDTH_8, EMMC_EXT_CSD_DDR_BUS_WIDTH_8 }, + { EMMC_EXT_CSD_BUS_WIDTH_4, EMMC_EXT_CSD_DDR_BUS_WIDTH_4 }, + { EMMC_EXT_CSD_BUS_WIDTH_1, EMMC_EXT_CSD_BUS_WIDTH_1 }, + }; + + ddrMode = EmmcGetDdrMode(cntlr, emmcDev, extCsd); + if (emmcDev->mmc.state.bits.hs400es == 0 && + emmcDev->mmc.state.bits.hs400 == 0 && + emmcDev->mmc.state.bits.hs200 == 0 && + cntlr->curDev->reg.csd.specVers >= MMC_CSD_SPEC_VER_4 && + (cntlr->caps.bits.cap4Bit | cntlr->caps.bits.cap8Bit) > 0) { + index = 1; + if (cntlr->caps.bits.cap8Bit > 0) { + index = 0; + } + for (; index < sizeof(busWidthBit) / sizeof(busWidthBit[0]); index++) { + width = busWidths[index]; + /* no DDR for 1-bit width. */ + if (width == BUS_WIDTH1) { + ddrMode = MMC_BUS_MODE_NULL; + } + error = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_BUS_WIDTH, busWidthBit[index][0]); + if (error != HDF_SUCCESS) { + continue; + } + MmcCntlrSetBusWidth(cntlr, width); + error = EmmcCheckExtCsd(cntlr, width); + if (error == HDF_SUCCESS) { + break; + } + } + /* switch DDR mode. */ + if (error == HDF_SUCCESS && ddrMode > MMC_BUS_MODE_NULL) { + error = EmmcSwitchDdrMode(cntlr, ddrMode, width, busWidthBit[index][1]); + } + if (error != HDF_SUCCESS) { + HDF_LOGE("EmmcSelectSwitchDdrMode: switch ddr mode fail!"); + return error; + } + } + return HDF_SUCCESS; +} + +static int32_t EmmcActivateHpiMechanism(struct MmcCntlr *cntlr, struct EmmcExtCsd *extCsd) +{ + int32_t error; + + if (extCsd->hpi == true) { + error = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_HPI_MGMT, 1); + if (error == HDF_SUCCESS) { + extCsd->hpiEnable = true; + } else if (error != HDF_MMC_ERR_SWITCH_FAIL) { + HDF_LOGE("EmmcActivateHpiMechanism: switch HPI_MGMT fail!"); + return error; + } + } + return HDF_SUCCESS; +} + +static int32_t EmmcSwitchOperationMode(struct MmcCntlr *cntlr) +{ + struct EmmcDevice *emmcDev = (struct EmmcDevice *)cntlr->curDev; + struct EmmcExtCsd *extCsd = &(emmcDev->emmcReg.extCsd); + int32_t error; + + if (extCsd->enhAreaEnable == true) { + error = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_ERASE_GROUP_DEF, 1); + if (error == HDF_SUCCESS) { + extCsd->eraseGroupDef = 1; + } else if (error != HDF_MMC_ERR_SWITCH_FAIL) { + HDF_LOGE("EmmcSwitchOperationMode: switch ERASE_GROUP_DEF fail!"); + return error; + } + } + + if ((extCsd->partConfig & EMMC_EXT_CSD_PART_CONFIG_ACCESS_MASK) > 0) { + /* No access to boot partition (default). */ + extCsd->partConfig &= ~EMMC_EXT_CSD_PART_CONFIG_ACCESS_MASK; + error = MmcSwitch(cntlr, EMMC_EXT_CSD_CMD_SET_NORMAL, EMMC_EXT_CSD_PARTITION_CONFIG, extCsd->partConfig); + if (error != HDF_SUCCESS && error != HDF_MMC_ERR_SWITCH_FAIL) { + HDF_LOGE("EmmcSwitchOperationMode: switch PARTITION_CONFIG fail!"); + return error; + } + } + + error = EmmcSelectBusSpeedMode(cntlr, emmcDev, extCsd); + if (error != HDF_SUCCESS) { + HDF_LOGE("EmmcSwitchOperationMode: select bus speed mode fail!"); + return error; + } + + error = EmmcSelectSwitchDdrMode(cntlr, emmcDev, extCsd); + if (error != HDF_SUCCESS) { + HDF_LOGE("EmmcSwitchOperationMode: select switch ddr mode fail!"); + return error; + } + return EmmcActivateHpiMechanism(cntlr, extCsd); +} + +static int32_t EmmcReadExtCsd(struct MmcCntlr *cntlr) +{ + uint8_t extCsd[EXT_CSD_BYTES_LEN] = {0}; + int32_t error; + + if (cntlr->curDev->reg.csd.specVers < MMC_CSD_SPEC_VER_4) { + return HDF_SUCCESS; + } + + error = MmcSendExtCsd(cntlr, extCsd, EXT_CSD_BYTES_LEN); + if (error != HDF_SUCCESS) { + HDF_LOGE("EmmcReadExtCsd: send cmd8 fail, error = %d.", error); + return error; + } + error = EmmcDecodeExtCsd(cntlr, extCsd, EXT_CSD_BYTES_LEN); + if (error != HDF_SUCCESS) { + HDF_LOGE("EmmcReadExtCsd: decode ext csd fail, error = %d.", error); + return error; + } + + return error; +} + +static int32_t EmmcSelect(struct MmcCntlr *cntlr, union MmcOcr ocr) +{ + union MmcOcr curOcr; + int32_t error; + + MmcGoIdleState(cntlr); + ocr.bits.hcs = 1; + /* set dev work voltage. */ + error = MmcSendOpCond(cntlr, ocr.ocrData, &curOcr.ocrData); + if (error != HDF_SUCCESS) { + HDF_LOGE("Emmc cmd1(set voltage) fail, error = %d.", error); + return error; + } + + error = MmcAllSendCid(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("Emmc cmd2(get cid) fail, error = %d.", error); + return error; + } + + /* card is identified. */ + cntlr->curDev->reg.rca = 1; + error = MmcSetRelativeAddr(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("Emmc cmd3(set rca) fail, error = %d.", error); + return error; + } + + error = MmcSendCsd(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("Emmc send cmd9(get csd) fail, error = %d.", error); + return error; + } + error = EmmcDecodeCsd(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("Emmc decode csd fail, error = %d.", error); + return error; + } + error = EmmcDecodeCid(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("Emmc decode cid fail, error = %d.", error); + return error; + } + error = MmcSelectCard(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("Emmc send cmd7 fail, error = %d.", error); + return error; + } + error = EmmcReadExtCsd(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("Emmc read ext csd fail, error = %d.", error); + return error; + } + + return EmmcSwitchOperationMode(cntlr); +} + +static int32_t EmmcDeviceAdd(struct MmcCntlr *cntlr) +{ + EmmcSetBlockCapacity(cntlr); + /* add dev. */ + if (MmcDeviceAdd(cntlr->curDev) != HDF_SUCCESS) { + HDF_LOGE("EmmcDeviceAdd: Add device fail!"); + return HDF_FAILURE; + } + cntlr->curDev->state.bits.present = 1; + return HDF_SUCCESS; +} + +static int32_t EmmcInit(struct MmcCntlr *cntlr) +{ + int32_t error; + union MmcOcr ocr = {0}; + + /* cmd1, detect emmc dev and get the voltage range. */ + error = MmcSendOpCond(cntlr, 0, &(ocr.ocrData)); + if (error != HDF_SUCCESS) { + HDF_LOGE("cmd1(detect emmc) fail, error = %d.", error); + return error; + } + + MmcCntlrSelectWorkVoltage(cntlr, &ocr); + if (cntlr->curDev->reg.ocr.ocrData == 0) { + HDF_LOGE("Emmc select work voltage fail!"); + return HDF_ERR_INVALID_PARAM; + } + /* work voltage is low voltage, host should switch. */ + if (cntlr->curDev->reg.ocr.bits.vdd1v65To1v95 > 0) { + HDF_LOGD("Emmc switch to 1.8V!"); + MmcCntlrSwitchVoltage(cntlr, VOLT_1V8); + } + + error = EmmcSelect(cntlr, cntlr->curDev->reg.ocr); + if (error != HDF_SUCCESS) { + return error; + } + + return EmmcDeviceAdd(cntlr); +} + +static int32_t EmmcDetect(struct MmcCntlr *cntlr) +{ + int32_t ret; + + HDF_LOGD("Detect emmc dev start..."); + MmcGoIdleState(cntlr); + ret = EmmcInit(cntlr); + if (ret == HDF_SUCCESS) { + HDF_LOGD("Detect emmc dev success! %s dev at address 0x%x!", + cntlr->curDev->state.bits.uhs ? "Ultra high speed" : + (cntlr->curDev->state.bits.highSpeed ? "High speed" : ""), + cntlr->curDev->reg.rca); + } + return ret; +} + +static int32_t SdSendAppCmd(struct MmcCntlr *cntlr, struct MmcCmd *cmd, + struct MmcData *data, uint32_t retryTimes) +{ + uint32_t i; + int32_t err; + + if (cntlr == NULL || cmd == NULL || retryTimes == 0) { + return HDF_ERR_INVALID_PARAM; + } + + for (i = 0; i <= retryTimes; i++) { + err = MmcAppCmd(cntlr, cmd->cmdCode); + if (err != HDF_SUCCESS) { + continue; + } + err = MmcSendCmd(cntlr, cmd, data, 1); + if (err == HDF_SUCCESS) { + break; + } + } + return err; +} + +static int32_t SdAcmdOpCond(struct MmcCntlr *cntlr, uint32_t arg, uint32_t *ocr) +{ + struct MmcCmd cmd = {0}; + int32_t err; + uint32_t i; + + cmd.cmdCode = SD_ACMD_OP_COND; + /* [31]reserved bit, [30]HCS, [29]reserved for eSD, [28]XPC, [27:25]reserved bits, [24]S18R, [23:0]VDD voltage. */ + cmd.argument = arg; + /* Broadcast Commands with Response(bcr). */ + cmd.respType = MMC_RESP_R3 | MMC_CMD_TYPE_BCR; + /* + * The host must poll the card (by repeatedly sending CMD1 or ACMD41) until the 'in-idle-state' bit in + * the card response indicates (by being set to 0) that the card completed its initialization processes + * and is ready for the next command. + */ + for (i = 0; i < INIT_CMD_RETRY_TIMES; i++) { + err = SdSendAppCmd(cntlr, &cmd, NULL, MMC_CMD_DEFAULT_RETRY_TIMES); + if (err != HDF_SUCCESS) { + break; + } + /* if probing, just single pass */ + if (arg == 0) { + break; + } + /* + * wait until init complete. + * 0--On Initialization; 1--Initialization Complete. + */ + if ((cmd.resp[0] & MMC_CARD_BUSY_STATUS) > 0) { + break; + } + err = HDF_ERR_TIMEOUT; + OsalMDelay(20); + } + if (ocr != NULL) { + *ocr = cmd.resp[0]; + } + + return err; +} + +static int32_t SdAcmdSdStatus(struct MmcCntlr *cntlr, uint32_t *ssr, uint32_t len) +{ + struct MmcCmd cmd = {0}; + struct MmcData data = {0}; + int32_t error; + uint32_t i; + + if (cntlr == NULL || ssr == NULL || len == 0) { + return HDF_ERR_INVALID_PARAM; + } + + cmd.cmdCode = SD_ACMD_SD_STATUS; + /* [31:0] stuff bits. */ + cmd.argument = 0; + /* Addressed (point-to-point) Data Transfer Commands (adtc), data transfer on DAT. */ + cmd.respType = MMC_RESP_SPI_R2 | MMC_RESP_R1 | MMC_CMD_TYPE_ADTC; + data.blockSize = SSR_BYTES_LEN; + data.blockNum = 1; + data.dataFlags = DATA_READ; + data.dataBuffer = (uint8_t *)ssr; + error = SdSendAppCmd(cntlr, &cmd, &data, 1); + if (error != HDF_SUCCESS) { + return error; + } + for (i = 0; i < len; i++) { + ssr[i] = MmcEndianConversion(ssr[i]); + } + return error; +} + +static int32_t SdAppSendScr(struct MmcCntlr *cntlr, uint32_t *scr, uint32_t len) +{ + struct MmcCmd cmd = {0}; + struct MmcData data = {0}; + int32_t error; + uint32_t i; + + if (cntlr == NULL || scr == NULL || len == 0) { + return HDF_ERR_INVALID_PARAM; + } + + cmd.cmdCode = SD_ACMD_SEND_SCR; + /* [31:0] stuff bits. */ + cmd.argument = 0; + /* Addressed (point-to-point) Data Transfer Commands (adtc), data transfer on DAT. */ + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_ADTC; + data.blockSize = SCR_BYTES_LEN; + data.blockNum = 1; + data.dataFlags = DATA_READ; + data.dataBuffer = (uint8_t *)scr; + error = SdSendAppCmd(cntlr, &cmd, &data, 1); + if (error != HDF_SUCCESS) { + return error; + } + for (i = 0; i < len; i++) { + scr[i] = MmcEndianConversion(scr[i]); + } + return error; +} + +static int32_t SdAcmdSetBusWidth(struct MmcCntlr *cntlr, uint32_t width) +{ + struct MmcCmd cmd = {0}; + + cmd.cmdCode = SD_ACMD_SET_BUS_WIDTH; + /* [31:2] stuff bits; [1:0]bus width: '00' = 1bit and '10' = 4bits. */ + cmd.argument = width; + /* Addressed (point-to-point) Commands(ac), no data transfer on DAT. */ + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_AC; + + return SdSendAppCmd(cntlr, &cmd, NULL, MMC_CMD_DEFAULT_RETRY_TIMES); +} + +static int32_t SdCmdSendIfCond(struct MmcCntlr *cntlr, uint32_t ocr) +{ + struct MmcCmd cmd = {0}; + int32_t err; + uint32_t vhs; + + cmd.cmdCode = SD_CMD_SEND_IF_COND; + /* + * [31:12]reserved bits, [11:8]supply voltage(VHS), [7:0]check pattern. + * VHS = 0001, 2.7-3.6V. + */ + vhs = ((ocr & 0xFF8000U) > 0) ? 1 : 0; + cmd.argument = (vhs << 8) | 0xAA; + cmd.respType = MMC_RESP_SPI_R7 | MMC_RESP_R7 | MMC_CMD_TYPE_BCR; + + err = MmcSendCmd(cntlr, &cmd, NULL, 1); + if (err != HDF_SUCCESS) { + return err; + } + /* + * Check pattern is used for the host to check validity of communication between the host and the card. + * In the Response, the card echoes back the check pattern set in argument. + * If check pattern is not matched, CMD8 communication is not valid. + */ + if ((cmd.resp[0] & 0xFF) != 0xAA) { + return HDF_ERR_IO; + } + return HDF_SUCCESS; +} + +static int32_t SdCmdSendRelativeAddr(struct MmcCntlr *cntlr, uint32_t *rca) +{ + int32_t error; + struct MmcCmd cmd = {0}; + + cmd.cmdCode = SD_CMD_SEND_RELATIVE_ADDR; + /* [31:0] stuff bits. */ + cmd.argument = 0; + cmd.respType = MMC_RESP_R6 | MMC_CMD_TYPE_BCR; + error = MmcSendCmd(cntlr, &cmd, NULL, MMC_CMD_DEFAULT_RETRY_TIMES); + if (error != HDF_SUCCESS) { + return error; + } + if (rca != NULL) { + /* New published RCA [31:16] of the card. */ + *rca = cmd.resp[0] >> 16; + } + return error; +} + +static int32_t SdCmdSwitchVoltage(struct MmcCntlr *cntlr) +{ + int32_t error; + struct MmcCmd cmd = {0}; + + /* Voltage switch command to change signaling level 3.3V to 1.8V. */ + cmd.cmdCode = SD_CMD_SWITCH_VOLTAGE; + /* [31:0] stuff bits. */ + cmd.argument = 0; + cmd.respType = MMC_RESP_R1 | MMC_CMD_TYPE_AC; + error = MmcSendCmd(cntlr, &cmd, NULL, 1); + if (error != HDF_SUCCESS) { + return error; + } + if (cmd.resp[0] & GENERAL_ERROR) { + return HDF_ERR_IO; + } + return HDF_SUCCESS; +} + +static int32_t SdCmdSwitchFunc(struct MmcCntlr *cntlr, struct SdSwitchFuncParam *param, + uint8_t *status, uint32_t len) +{ + struct MmcCmd cmd = {0}; + struct MmcData data = {0}; + + cmd.cmdCode = SD_CMD_SWITCH_FUNC; + /* + * [31]Mode. The switch command can be used in two modes: + * Mode 0 (Check function) is used to query if the card supports a specific function or functions. + * Mode 1 (set function) is used to switch the functionality of the card. + */ + cmd.argument = (param->mode << 31) | 0x00FFFFFF; + /* + * [30:24] reserved(All '0'); [23:20] reserved for function group 6(All '0' or 0xF); + * [19:16] reserved for function group 5(All '0' or 0xF); [15:12] function group 4 for Power Limit; + * [11:8] function group 3 for Drive Strength; [7:4] function group 2 for command system; + * [3:0] function group 1 for access mode. + */ + cmd.argument &= ~(0xFU << (param->group * 4)); + cmd.argument |= (param->value & 0xF) << (param->group * 4); + cmd.respType = MMC_RESP_SPI_R1 | MMC_RESP_R1 | MMC_CMD_TYPE_ADTC; + /* + * As a response to the switch function command, the SD Memory Card will send R1 response on the CMD line, + * and 512 bits of status on the DAT lines. + */ + data.blockSize = len; + data.blockNum = 1; + data.dataFlags = DATA_READ; + data.dataBuffer = status; + + return MmcSendCmd(cntlr, &cmd, &data, 1); +} + +static int32_t SdDecodeScr(struct MmcCntlr *cntlr) +{ + struct SdScr *scr = NULL; + uint32_t *rawScr = NULL; + struct SdDevice *sdDev = NULL; + uint32_t scrStruct; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + sdDev = (struct SdDevice *)cntlr->curDev; + rawScr = sdDev->reg.rawScr; + scr = &(sdDev->reg.scr); + + /* + * SCR_STRUCTURE: [63:60]; + * SCR_STRUCTURE equal 0, SCR version 1.0; SCR_STRUCTURE equal 1-15, reserved. + */ + scrStruct = (uint8_t)MmcParseBits(rawScr, SCR_BITS, 60, 4); + if (scrStruct != 0) { + HDF_LOGE("SdDecodeScr: scrStruct is invalid!"); + return HDF_ERR_INVALID_PARAM; + } + /* + * SD_SPEC: [59:56]. + * Describes the SD Memory Card Physical Layer Specification version supported by this card. + * SD_SPEC = 0 , Version 1.0-1.01; SD_SPEC = 1, Version 1.1; SD_SPEC = 2, Version >= 2.0. + */ + scr->sdSpec = (uint8_t)MmcParseBits(rawScr, SCR_BITS, 56, 4); + if (scr->sdSpec == SD_SCR_SPEC_2) { + /* SD_SPEC3: [47:47] */ + scr->sdSpec3 = (uint8_t)MmcParseBits(rawScr, SCR_BITS, 47, 1); + } + /* + * SD_BUS_WIDTHS: [51:48]. + * SD_BUS_WIDTHS equal 0, 1 bit (DAT0); SD_BUS_WIDTHS equal 2, 4 bit (DAT0-3). + */ + scr->sdBusWidths = (uint8_t)MmcParseBits(rawScr, SCR_BITS, 48, 4); + /* CMD_SUPPORT: [35:32] */ + scr->cmdSupport = (uint8_t)MmcParseBits(rawScr, SCR_BITS, 32, 2); + return HDF_SUCCESS; +} + +static int32_t SdDecodeSSr(struct MmcCntlr *cntlr, uint32_t *rawSsr, uint32_t len) +{ + struct SdSsr *ssr = NULL; + struct SdScr *scr = NULL; + struct SdDevice *sdDev = NULL; + uint32_t eraseSize, eraseTimeout; + + if (cntlr == NULL || cntlr->curDev == NULL || rawSsr == NULL || len == 0) { + return HDF_ERR_INVALID_PARAM; + } + + sdDev = (struct SdDevice *)cntlr->curDev; + ssr = &(sdDev->reg.ssr); + scr = &(sdDev->reg.scr); + /* SPEED_CLASS: [447:440] */ + ssr->speedClass = MmcParseBits(rawSsr, SSR_BITS, 440, 8); + /* AU_SIZE: [431: 428]. */ + ssr->auSize = MmcParseBits(rawSsr, SSR_BITS, 428, 4); + if (ssr->auSize > 0) { + if ((ssr->auSize <= MMC_MAX_BLOCKSIZE_SHIFT) || scr->sdSpec3 > 0) { + ssr->auValue = 1 << (ssr->auSize + 4); + /* + * ERASE_SIZE: [423:408]. If this field is set to 0, the erase timeout caculation is not supported. + * ERASE_SIZE = 1, value = 1AU; ERASE_SIZE = 2, value = 2AU... + */ + eraseSize = MmcParseBits(rawSsr, SSR_BITS, 408, 16); + /* ERASE_TIMEOUT: [407:402] */ + eraseTimeout = MmcParseBits(rawSsr, SSR_BITS, 402, 6); + if (eraseSize > 0) { + ssr->eraseTimeout = (eraseTimeout * 1000) / eraseSize; + /* ERASE_OFFSET: [401:400] */ + ssr->eraseOffset = 1000 * MmcParseBits(rawSsr, SSR_BITS, 400, 2); + } + } else { + HDF_LOGD("SD Status: Invalid AU."); + } + } + /* UHS_SPEED_GRADE: [399:396] */ + ssr->uhsSpeedGrade = MmcParseBits(rawSsr, SSR_BITS, 396, 4); + return HDF_SUCCESS; +} + +static void SdDecodeCid(struct MmcCntlr *cntlr) +{ + struct MmcCid *cid = NULL; + uint32_t *rawCid = NULL; + uint32_t i; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return; + } + + rawCid = cntlr->curDev->reg.rawCid; + cid = &(cntlr->curDev->reg.cid); + /* Manufacturer ID(MID): [127:120] */ + cid->mid = MmcParseBits(rawCid, CID_BITS, 120, 8); + /* OEM/Application ID(OID): [119:104] */ + cid->oid = MmcParseBits(rawCid, CID_BITS, 104, 16); + /* Product name(PNM): [103:64] */ + for (i = 0; i < 5; i++) { + cid->pnm[i] = MmcParseBits(rawCid, CID_BITS, 96 - (i * 8), 8); + } + cid->pnm[5] = '\0'; + /* + * Product revision(PRV): [63:56]. + * The product revision is composed of two Binary Coded Decimal (BCD) digits, four bits each, + * representingan "n.m" revision number. + */ + cid->hwPrv = MmcParseBits(rawCid, CID_BITS, 60, 4); + cid->fwPrv = MmcParseBits(rawCid, CID_BITS, 56, 4); + /* Product serial number(PSN): [55:24] */ + cid->psn = MmcParseBits(rawCid, CID_BITS, 24, 32); + /* + * Manufacturing date(MDT): [19:8]. + * The manufacturing date composed of two hexadecimal digits, one is 8 bit representing the year(y) + * and the other is four bits representing the month(m). + * The "m" field [11:8] is the month code. 1 = January. + * The "y" field [19:12] is the year code. 0 = 2000. + */ + cid->year = MmcParseBits(rawCid, CID_BITS, 12, 8) + 2000; + cid->month = MmcParseBits(rawCid, CID_BITS, 8, 4); +} + +static void SdSetBlockCapacity(struct MmcCntlr *cntlr) +{ + struct SdDevice *sdDev = (struct SdDevice *)cntlr->curDev; + uint32_t gibVal, mibVal; + + sdDev->mmc.eraseSize = sdDev->mmc.reg.csd.eraseSize; + sdDev->mmc.capacity = sdDev->mmc.reg.csd.capacity << + (sdDev->mmc.reg.csd.readBlkLen - MMC_MAX_BLOCKSIZE_SHIFT); + + gibVal = sdDev->mmc.capacity >> 21; + mibVal = (sdDev->mmc.capacity & ~(gibVal << 21)) >> 11; + HDF_LOGD("SD dev capacity %d.%d Gib", gibVal, mibVal); +} + +static void SdDecodeCsdRev1Field(struct MmcCntlr *cntlr, struct MmcCsd *csd, uint32_t *rawCsd) +{ + uint32_t unit, factor; + + /* TAAC: [119:112]; TAAC bit position-->Time unit: [2:0], Multiplier factor: [6:3]. */ + factor = MmcParseBits(rawCsd, CSD_BITS, 115, 4); + unit = MmcParseBits(rawCsd, CSD_BITS, 112, 3); + csd->taccNs = (g_taccUnit[unit] * g_commFactor[factor] + 9) / 10; + /* NSAC: [111:104], the unit for NSAC is 100 clock cycles */ + csd->taccClks = MmcParseBits(rawCsd, CSD_BITS, 104, 8) * 100; + + /* TRAN_SPEED: [103:96]; TRAN_SPEED bit-->Frequency unit: [2:0], Multiplier factor: [6:3]. */ + factor = MmcParseBits(rawCsd, CSD_BITS, 99, 4); + unit = MmcParseBits(rawCsd, CSD_BITS, 96, 3); + csd->maxDtr = g_tranSpeedUnit[unit] * g_commFactor[factor]; + /* card command classes: [95:84] */ + csd->ccc = MmcParseBits(rawCsd, CSD_BITS, 84, 12); + /* C_SIZE: [73:62] */ + unit = MmcParseBits(rawCsd, CSD_BITS, 62, 12); + /* C_SIZE_MULT: [49:47] */ + factor = MmcParseBits(rawCsd, CSD_BITS, 47, 3); + csd->capacity = (1 + unit) << (factor + 2); + /* READ_BL_LEN: [83:80]. */ + csd->readBlkLen = MmcParseBits(rawCsd, CSD_BITS, 80, 4); + /* READ_BL_PARTIAL: [79:79] */ + csd->rdPartial = MmcParseBits(rawCsd, CSD_BITS, 79, 1); + /* WRITE_BLK_MISALIGN: [78:78] */ + csd->wrMisalign = MmcParseBits(rawCsd, CSD_BITS, 78, 1); + /* READ_BLK_MISALIGN: [77:77] */ + csd->rdMisalign = MmcParseBits(rawCsd, CSD_BITS, 77, 1); + /* Write speed factor(R2W_FACTOR) :[28:26] */ + csd->r2wFactor = MmcParseBits(rawCsd, CSD_BITS, 26, 3); + /* WRITE_BL_LEN: [25:22] */ + csd->writeBlkLen = MmcParseBits(rawCsd, CSD_BITS, 22, 4); + /* WRITE_BL_PARTIAL: [21:21] */ + csd->wrPartial = MmcParseBits(rawCsd, CSD_BITS, 21, 1); + /* + * erase single block enable(ERASE_BLK_EN): [46:46] + * If ERASE_BLK_EN is '0' erase area is unit of SECTOR_SIZE. + * if ERASE_BLK_EN is '1' erase area is unit of SECTOR_SIZE or unit of WRITE_BL_LEN. + */ + if (MmcParseBits(rawCsd, CSD_BITS, 46, 1) == 1) { + csd->eraseSize = 1; + } else if (csd->writeBlkLen >= MMC_MAX_BLOCKSIZE_SHIFT) { + /* + * erase sector size(SECTOR_SIZE): [45:39]. + * The actual size is computed by increasing this number by one. + * A value of zero means 1 write block, 127 means 128 write blocks. + */ + csd->eraseSize = MmcParseBits(rawCsd, CSD_BITS, 39, 7) + 1; + csd->eraseSize <<= (csd->writeBlkLen - MMC_MAX_BLOCKSIZE_SHIFT); + } +} + +static void SdDecodeCsdRev2Field(struct MmcCntlr *cntlr, struct MmcCsd *csd, uint32_t *rawCsd) +{ + uint32_t unit, factor; + + cntlr->curDev->state.bits.blockAddr = 1; + /* TRAN_SPEED: [103:96]; TRAN_SPEED bit-->Frequency unit: [2:0], Multiplier factor: [6:3]. */ + factor = MmcParseBits(rawCsd, CSD_BITS, 99, 4); + unit = MmcParseBits(rawCsd, CSD_BITS, 96, 3); + csd->maxDtr = g_tranSpeedUnit[unit] * g_commFactor[factor]; + /* card command classes: [95:84] */ + csd->ccc = MmcParseBits(rawCsd, CSD_BITS, 84, 12); + /* device size(C_SIZE): [69:48] */ + csd->cSize = MmcParseBits(rawCsd, CSD_BITS, 48, 22); + /* The Minimum value of C_SIZE for SDXC in CSD Version 2.0 is 00FFFFh(65535). */ + if (csd->cSize >= 0xFFFF) { + cntlr->curDev->state.bits.sdxc = 1; + } + /* memory capacity = (C_SIZE + 1) * 512KByte */ + csd->capacity = (1 + csd->cSize) << 10; + + csd->taccNs = 0; + csd->taccClks = 0; + csd->rdPartial = 0; + csd->readBlkLen = MMC_MAX_BLOCKSIZE_SHIFT; + csd->rdMisalign = 0; + csd->wrMisalign = 0; + csd->writeBlkLen = MMC_MAX_BLOCKSIZE_SHIFT; + csd->wrPartial = 0; + csd->r2wFactor = 2; + csd->eraseSize = 1; +} + +static int32_t SdDecodeCsd(struct MmcCntlr *cntlr) +{ + struct MmcCsd *csd = NULL; + uint32_t *rawCsd = NULL; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + rawCsd = cntlr->curDev->reg.rawCsd; + csd = &(cntlr->curDev->reg.csd); + + /* CSD_STRUCTURE: [127:126]. */ + csd->structure = MmcParseBits(rawCsd, CSD_BITS, 126, 2); + if (csd->structure == 0) { + /* CSD Version 1.0 */ + SdDecodeCsdRev1Field(cntlr, csd, rawCsd); + } else if (csd->structure == 1) { + /* CSD Version 2.0 */ + SdDecodeCsdRev2Field(cntlr, csd, rawCsd); + } else { + HDF_LOGE("SdDecodeCsd: not support, structure = %d.", csd->structure); + return HDF_ERR_NOT_SUPPORT; + } + + return HDF_SUCCESS; +} + +static uint32_t SdGetMaxClock(struct MmcCntlr *cntlr) +{ + uint32_t clock = 0xFFFFFFFF; + struct MmcDevice *mmcDev = cntlr->curDev; + struct SdDevice *sdDev = (struct SdDevice *)mmcDev; + + if (mmcDev->state.bits.highSpeed == 1) { + if (sdDev->reg.swCaps.hsMaxDtr > 0) { + clock = sdDev->reg.swCaps.hsMaxDtr; + } + } else if (mmcDev->reg.csd.maxDtr > 0) { + clock = mmcDev->reg.csd.maxDtr; + } + + if (clock > cntlr->freqMax) { + clock = cntlr->freqMax; + } + + return clock; +} + +static int32_t SdSelect(struct MmcCntlr *cntlr, uint32_t *rocr) +{ + int err; + bool try = false; + union MmcOcr ocr = cntlr->curDev->reg.ocr; + + do { + /* dev state: ready -> idle. */ + MmcGoIdleState(cntlr); + /* dev state: idle -> idle. */ + err = SdCmdSendIfCond(cntlr, cntlr->curDev->reg.ocr.ocrData); + if (err == HDF_SUCCESS) { + ocr.bits.hcs = 1; + } + if (cntlr->caps.bits.xpc330 == 1 || cntlr->caps.bits.xpc300 == 1 || cntlr->caps.bits.xpc180 == 1) { + ocr.bits.sdXpc = 1; + } + if (MmcCntlrSupportUhs(cntlr) == true && try == false) { + ocr.bits.s18r = 1; + } + /* dev state: idle -> ready. */ + err = SdAcmdOpCond(cntlr, ocr.ocrData, rocr); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdSelect: acmd41 fail, err = %d.", err); + return err; + } + + /* host not support sd procotol 3.0 */ + if (cntlr->caps.bits.sdSupportProtocol3 == 0) { + break; + } + try = false; + /* + * Send cmd 11 to switch the volt. If host or device do not support, + * we need set 3.3v again. + */ + if (rocr != NULL && (*rocr & 0x41000000) == 0x41000000) { + /* switch host and card to 1.8V + * dev state: ready -> ready. + */ + err = SdCmdSwitchVoltage(cntlr); + if (err == HDF_SUCCESS) { + err = MmcCntlrSwitchVoltage(cntlr, VOLT_1V8); + } + if (err != HDF_SUCCESS) { + ocr.bits.s18r = 0; + try = true; + } + } + }while (try == true); + + /* get cid, dev state: ready -> ident. */ + err = MmcAllSendCid(cntlr); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdSelect: cmd2 fail, err = %d.", err); + return err; + } + SdDecodeCid(cntlr); + return err; +} + +static int32_t SdReadCsd(struct MmcCntlr *cntlr) +{ + int32_t error; + + error = MmcSendCsd(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("SdReadCsd: cmd9 fail, error = %d.", error); + return error; + } + return SdDecodeCsd(cntlr); +} + +static int32_t SdReadScr(struct MmcCntlr *cntlr) +{ + int32_t error; + struct SdDevice *dev = (struct SdDevice *)cntlr->curDev; + + error = SdAppSendScr(cntlr, dev->reg.rawScr, SCR_LEN); + if (error != HDF_SUCCESS) { + HDF_LOGE("SdReadScr: acmd51 fail, error = %d.", error); + return error; + } + return SdDecodeScr(cntlr); +} + +static int32_t SdReadSsr(struct MmcCntlr *cntlr) +{ + int32_t err; + uint32_t rawSsr[SSR_LEN] = {0}; + + /* don't support ACMD. */ + if ((cntlr->curDev->reg.csd.ccc & MMC_CSD_CCC_APP_SPEC) == 0) { + return HDF_SUCCESS; + } + + err = SdAcmdSdStatus(cntlr, rawSsr, SSR_LEN); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdReadSsr: acmd13 fail, err = %d.", err); + return err; + } + return SdDecodeSSr(cntlr, rawSsr, SSR_LEN); +} + +static int32_t SdReadSwitchCapbility(struct MmcCntlr *cntlr) +{ + int32_t err; + uint8_t status[SD_SWITCH_FUNCTION_STATUS_BYTES_LEN] = {0}; + struct SdDevice *dev = (struct SdDevice *)cntlr->curDev; + struct SdSwitchFuncParam param = {0}; + + if (dev->reg.scr.sdSpec < SD_SCR_SPEC_1) { + return HDF_SUCCESS; + } + if ((cntlr->curDev->reg.csd.ccc & MMC_CSD_CCC_SWITCH) == 0) { + return HDF_SUCCESS; + } + + param.mode = SD_SWITCH_FUNC_MODE_CHECK; + param.group = SD_SWITCH_FUNC_GROUP_1; + param.value = 1; + /* The data(status) is in reverse order relative to the protocol. */ + err = SdCmdSwitchFunc(cntlr, ¶m, status, SD_SWITCH_FUNCTION_STATUS_BYTES_LEN); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdReadSwitchCapbility: swutch func group 1 fail, err = %d.", err); + return err; + } + /* [415:400]Function Group 1 information, [407:400]-->status[13]. */ + if ((status[13] & SD_BUS_SPEED_MODE_HS) > 0) { + dev->reg.swCaps.hsMaxDtr = SD_HIGH_SPEED_MAX_DTR; + } + + if (dev->reg.scr.sdSpec3 == 1) { + dev->reg.swCaps.sdSpec3BusMode.data = status[13]; + param.group = SD_SWITCH_FUNC_GROUP_3; + err = SdCmdSwitchFunc(cntlr, ¶m, status, SD_SWITCH_FUNCTION_STATUS_BYTES_LEN); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdReadSwitchCapbility: swutch func group 3 fail!"); + return err; + } + /* [447:432]Function Group 3 information, [447:440]-->status[9]. */ + dev->reg.swCaps.sdSpec3DrvType = (enum SdDrvType)status[9]; + param.group = SD_SWITCH_FUNC_GROUP_4; + err = SdCmdSwitchFunc(cntlr, ¶m, status, SD_SWITCH_FUNCTION_STATUS_BYTES_LEN); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdReadSwitchCapbility: swutch func group 4 fail!"); + return err; + } + /* [463:448]Function Group 4 information, [463:456]-->status[7]. */ + dev->reg.swCaps.sdSpec3CurrLimit = (enum SdMaxCurrentLimitBit)status[7]; + } + return HDF_SUCCESS; +} + +static void SdFillBusSpeedMode(struct MmcCntlr *cntlr) +{ + struct SdDevice *dev = (struct SdDevice *)cntlr->curDev; + + if (MmcCntlrSupportUhs(cntlr) == false || dev->reg.scr.sdSpec3 == 0) { + dev->busSpeedMode = SD_BUS_SPEED_MODE_DS; + return; + } + + /* select max speed mode supported by host and device. */ + if ((cntlr->caps.bits.uhsSdr104 == 1) && (dev->reg.swCaps.sdSpec3BusMode.bits.uhsSdr104 == 1)) { + dev->busSpeedMode = SD_BUS_SPEED_MODE_UHS_SDR104; + } else if ((cntlr->caps.bits.uhsDdr50 == 1) && (dev->reg.swCaps.sdSpec3BusMode.bits.uhsDdr50 == 1)) { + dev->busSpeedMode = SD_BUS_SPEED_MODE_UHS_DDR50; + } else if ((cntlr->caps.bits.uhsSdr104 == 1 || cntlr->caps.bits.uhsSdr50 == 1) && + (dev->reg.swCaps.sdSpec3BusMode.bits.uhsSdr50 == 1)) { + dev->busSpeedMode = SD_BUS_SPEED_MODE_UHS_SDR50; + } else if ((cntlr->caps.bits.uhsSdr104 == 1 || cntlr->caps.bits.uhsSdr50 == 1 || + cntlr->caps.bits.uhsSdr25 == 1) && (dev->reg.swCaps.sdSpec3BusMode.bits.uhsSdr25 == 1)) { + dev->busSpeedMode = SD_BUS_SPEED_MODE_UHS_SDR25; + } else if ((cntlr->caps.bits.uhsSdr104 == 1 || cntlr->caps.bits.uhsSdr50 == 1 || + cntlr->caps.bits.uhsSdr25 == 1 || cntlr->caps.bits.uhsSdr12 == 1) && + (dev->reg.swCaps.sdSpec3BusMode.bits.uhsSdr12 == 1)) { + dev->busSpeedMode = SD_BUS_SPEED_MODE_UHS_SDR12; + } +} + +static int32_t SdReadRegisters(struct MmcCntlr *cntlr) +{ + int32_t error; + + /* get SCR */ + error = SdReadScr(cntlr); + if (error != HDF_SUCCESS) { + return error; + } + + /* get SSR */ + error = SdReadSsr(cntlr); + if (error != HDF_SUCCESS) { + return error; + } + + /* get sw cap */ + error = SdReadSwitchCapbility(cntlr); + if (error != HDF_SUCCESS) { + return error; + } + + if (MmcCntlrDevReadOnly(cntlr) == true) { + cntlr->curDev->state.bits.readonly = 1; + } + SdFillBusSpeedMode(cntlr); + return HDF_SUCCESS; +} + +static int32_t SdExecuteTuning(struct MmcCntlr *cntlr) +{ + struct SdDevice *dev = (struct SdDevice *)cntlr->curDev; + + if (dev->busSpeedMode == SD_BUS_SPEED_MODE_UHS_DDR50) { + return MmcCntlrTune(cntlr, SD_CMD_SWITCH_FUNC); + } + if ((dev->busSpeedMode == SD_BUS_SPEED_MODE_UHS_SDR104) || + (dev->busSpeedMode == SD_BUS_SPEED_MODE_UHS_SDR50)) { + return MmcCntlrTune(cntlr, SD_CMD_SEND_TUNING_BLOCK); + } + return HDF_SUCCESS; +} + +static uint32_t SdGetDevMaxCurrentLimitValue(enum SdMaxCurrentLimitBit devCap) +{ + uint32_t currentLimit = 0; + + if (devCap == SD_MAX_CURRENT_LIMIT_800) { + currentLimit = SD_MAX_CURRENT_LIMIT_800_VALUE; + } else if (devCap == SD_MAX_CURRENT_LIMIT_600) { + currentLimit = SD_MAX_CURRENT_LIMIT_600_VALUE; + } else if (devCap == SD_MAX_CURRENT_LIMIT_400) { + currentLimit = SD_MAX_CURRENT_LIMIT_400_VALUE; + } else if (devCap == SD_MAX_CURRENT_LIMIT_200) { + currentLimit = SD_MAX_CURRENT_LIMIT_200_VALUE; + } + return currentLimit; +} + +static uint32_t SdGetMaxCurrentLimitValue(union MmcCaps *hostCap, enum SdMaxCurrentLimitBit devCap) +{ + uint32_t currentLimit; + + /* get max support by dev. */ + currentLimit = SdGetDevMaxCurrentLimitValue(devCap); + if (hostCap->bits.maxCurrentLimit800 == 1) { + currentLimit = ((currentLimit < SD_MAX_CURRENT_LIMIT_800_VALUE) ? + currentLimit : SD_MAX_CURRENT_LIMIT_800_VALUE); + } else if (hostCap->bits.maxCurrentLimit600 == 1) { + currentLimit = ((currentLimit < SD_MAX_CURRENT_LIMIT_600_VALUE) ? + currentLimit : SD_MAX_CURRENT_LIMIT_600_VALUE); + } else if (hostCap->bits.maxCurrentLimit400 == 1) { + currentLimit = ((currentLimit < SD_MAX_CURRENT_LIMIT_400_VALUE) ? + currentLimit : SD_MAX_CURRENT_LIMIT_400_VALUE); + } else if (hostCap->bits.maxCurrentLimit200 == 1) { + currentLimit = ((currentLimit < SD_MAX_CURRENT_LIMIT_200_VALUE) ? + currentLimit : SD_MAX_CURRENT_LIMIT_200_VALUE); + } + return currentLimit; +} + +static int32_t SdSetMaxCurrentLimit(struct MmcCntlr *cntlr) +{ + struct SdDevice *dev = (struct SdDevice *)cntlr->curDev; + uint8_t status[SD_SWITCH_FUNCTION_STATUS_BYTES_LEN] = {0}; + struct SdSwitchFuncParam param = {0}; + uint32_t currentLimit; + int32_t err; + + if ((dev->busSpeedMode == SD_BUS_SPEED_MODE_UHS_SDR104) || + (dev->busSpeedMode == SD_BUS_SPEED_MODE_UHS_DDR50) || + (dev->busSpeedMode == SD_BUS_SPEED_MODE_UHS_SDR50)) { + currentLimit = SdGetMaxCurrentLimitValue(&(cntlr->caps), dev->reg.swCaps.sdSpec3CurrLimit); + } else { + currentLimit = SD_MAX_CURRENT_LIMIT_200_VALUE; + } + + param.mode = SD_SWITCH_FUNC_MODE_SET; + param.group = SD_SWITCH_FUNC_GROUP_4; + param.value = currentLimit; + /* Current Limit is selected by CMD6 Function Group 4. */ + err = SdCmdSwitchFunc(cntlr, ¶m, status, SD_SWITCH_FUNCTION_STATUS_BYTES_LEN); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdSetMaxCurrentLimit: swutch func group 3 fail!"); + return err; + } + if (((status[15] >> 4) & 0x0F) != currentLimit) { + HDF_LOGD("SdSetMaxCurrentLimit: status not match!"); + } + + return HDF_SUCCESS; +} + +static int32_t SdSetBusSpeedMode(struct MmcCntlr *cntlr) +{ + struct SdDevice *dev = (struct SdDevice *)cntlr->curDev; + uint8_t status[SD_SWITCH_FUNCTION_STATUS_BYTES_LEN] = {0}; + struct SdSwitchFuncParam param = {0}; + int32_t err; + enum MmcBusTiming timing; + + switch (dev->busSpeedMode) { + case SD_BUS_SPEED_MODE_UHS_SDR104: + timing = BUS_TIMING_UHS_SDR104; + dev->reg.swCaps.uhsMaxDtr = SD_UHS_SDR104_MAX_DTR; + break; + case SD_BUS_SPEED_MODE_UHS_DDR50: + timing = BUS_TIMING_UHS_DDR50; + dev->reg.swCaps.uhsMaxDtr = SD_UHS_DDR50_MAX_DTR; + break; + case SD_BUS_SPEED_MODE_UHS_SDR50: + timing = BUS_TIMING_UHS_SDR50; + dev->reg.swCaps.uhsMaxDtr = SD_UHS_SDR50_MAX_DTR; + break; + case SD_BUS_SPEED_MODE_UHS_SDR25: + timing = BUS_TIMING_UHS_SDR25; + dev->reg.swCaps.uhsMaxDtr = SD_UHS_SDR25_MAX_DTR; + break; + case SD_BUS_SPEED_MODE_UHS_SDR12: + timing = BUS_TIMING_UHS_SDR12; + dev->reg.swCaps.uhsMaxDtr = SD_UHS_SDR12_MAX_DTR; + break; + default: + return HDF_SUCCESS; + } + /* Bus Speed Mode is selected by CMD6 Function Group 1. */ + param.mode = SD_SWITCH_FUNC_MODE_SET; + param.group = SD_SWITCH_FUNC_GROUP_1; + param.value = dev->busSpeedMode; + err = SdCmdSwitchFunc(cntlr, ¶m, status, SD_SWITCH_FUNCTION_STATUS_BYTES_LEN); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdSetBusSpeedMode: swutch func group 1 fail!"); + return err; + } + if ((status[16] & 0xF) != dev->busSpeedMode) { + HDF_LOGD("SdSetBusSpeedMode: status not match!"); + } else { + MmcCntlrSetBusTiming(cntlr, timing); + MmcCntlrSetClock(cntlr, dev->reg.swCaps.uhsMaxDtr); + } + + return HDF_SUCCESS; +} + +static int32_t SdSwitch4BitBusWidth(struct MmcCntlr *cntlr, struct SdDevice *dev) +{ + int32_t err = HDF_SUCCESS; + + if ((dev->reg.scr.sdBusWidths & SD_SCR_BUS_WIDTHS_4) > 0 && + (cntlr->caps.bits.cap4Bit > 0)) { + err = SdAcmdSetBusWidth(cntlr, BUS_WIDTH4); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdSwitch4BitBusWidth: set 4-bits bus width fail!"); + return err; + } + MmcCntlrSetBusWidth(cntlr, BUS_WIDTH4); + } + return err; +} + +static int32_t SdUltraHighSpeedDevInit(struct MmcCntlr *cntlr) +{ + int32_t err; + struct SdDevice *dev = (struct SdDevice *)cntlr->curDev; + + if (dev->reg.scr.sdSpec3 == 0) { + return HDF_SUCCESS; + } + if ((cntlr->curDev->reg.csd.ccc & MMC_CSD_CCC_SWITCH) == 0) { + return HDF_SUCCESS; + } + + err = SdSwitch4BitBusWidth(cntlr, dev); + if (err != HDF_SUCCESS) { + return err; + } + err = SdSetMaxCurrentLimit(cntlr); + if (err != HDF_SUCCESS) { + return err; + } + err = SdSetBusSpeedMode(cntlr); + if (err != HDF_SUCCESS) { + return err; + } + return SdExecuteTuning(cntlr); +} + +static int32_t SdSwitchHighSpeed(struct MmcCntlr *cntlr) +{ + int32_t err; + struct SdDevice *dev = (struct SdDevice *)cntlr->curDev; + uint8_t status[SD_SWITCH_FUNCTION_STATUS_BYTES_LEN] = {0}; + struct SdSwitchFuncParam param = {0}; + + if (dev->reg.swCaps.hsMaxDtr == 0) { + return HDF_ERR_NOT_SUPPORT; + } + if (dev->reg.scr.sdSpec < SD_SCR_SPEC_1) { + return HDF_ERR_NOT_SUPPORT; + } + if (cntlr->caps.bits.highSpeed == 0) { + return HDF_ERR_NOT_SUPPORT; + } + if ((cntlr->curDev->reg.csd.ccc & MMC_CSD_CCC_SWITCH) == 0) { + return HDF_ERR_NOT_SUPPORT; + } + /* Bus Speed Mode is selected by CMD6 Function Group 1. */ + param.mode = SD_SWITCH_FUNC_MODE_SET; + param.group = SD_SWITCH_FUNC_GROUP_1; + param.value = SD_BUS_SPEED_MODE_HS; + err = SdCmdSwitchFunc(cntlr, ¶m, status, SD_SWITCH_FUNCTION_STATUS_BYTES_LEN); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdSwitchHighSpeed: switch func group 1 fail!"); + return err; + } + if ((status[16] & 0xF) != SD_BUS_SPEED_MODE_HS) { + return HDF_ERR_NOT_SUPPORT; + } + return HDF_SUCCESS; +} + +static int32_t SdHighSpeedDevInit(struct MmcCntlr *cntlr) +{ + int err; + struct SdDevice *sdDev = (struct SdDevice *)cntlr->curDev; + + err = SdSwitchHighSpeed(cntlr); + if (err == HDF_SUCCESS) { + cntlr->curDev->state.bits.highSpeed = 1; + MmcCntlrSetBusTiming(cntlr, BUS_TIMING_SD_HS); + } else if (err != HDF_ERR_NOT_SUPPORT) { + HDF_LOGE("SdHighSpeedDevInit: switch high speed fail!"); + return err; + } + MmcCntlrSetClock(cntlr, SdGetMaxClock(cntlr)); + return SdSwitch4BitBusWidth(cntlr, sdDev); +} + +static int32_t SdDeviceAdd(struct MmcCntlr *cntlr) +{ + /* The SD dev must be removable. */ + cntlr->curDev->state.bits.removeable = 1; + SdSetBlockCapacity(cntlr); + /* add dev. */ + if (MmcDeviceAdd(cntlr->curDev) != HDF_SUCCESS) { + HDF_LOGE("SdDeviceAdd: add device fail!"); + return HDF_FAILURE; + } + cntlr->curDev->state.bits.present = 1; + return HDF_SUCCESS; +} + +static int32_t SdInit(struct MmcCntlr *cntlr) +{ + int32_t error; + union MmcOcr ocr = {0}; + + /* acmd41, detect sd dev and get the voltage range. dev state: idle -> ready. */ + error = SdAcmdOpCond(cntlr, 0, &(ocr.ocrData)); + if (error != HDF_SUCCESS) { + HDF_LOGE("acmd41(detect sd) fail, err = %d!", error); + return error; + } + + MmcCntlrSelectWorkVoltage(cntlr, &ocr); + if (cntlr->curDev->reg.ocr.ocrData == 0) { + HDF_LOGE("SD work voltage is invalid!"); + return HDF_ERR_INVALID_PARAM; + } + error = SdSelect(cntlr, &(ocr.ocrData)); + if (error != HDF_SUCCESS) { + return error; + } + /* get RCA. dev state: ident -> stby. */ + error = SdCmdSendRelativeAddr(cntlr, &(cntlr->curDev->reg.rca)); + if (error != HDF_SUCCESS) { + HDF_LOGE("cmd3(get RCA) fail!, error = %d.", error); + return error; + } + /* get CSD, CMD9 should send in stby. dev state: stby -> stby. */ + error = SdReadCsd(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("sd read csd fail!, error = %d.", error); + return error; + } + /* select card. dev state: stby -> tran. */ + error = MmcSelectCard(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("cmd7(select card) fail!, error = %d.", error); + return error; + } + /* dev state: tran -> tran. */ + error = SdReadRegisters(cntlr); + if (error != HDF_SUCCESS) { + return error; + } + + if (ocr.bits.s18r == 1) { + /* uhs dev set */ + error = SdUltraHighSpeedDevInit(cntlr); + if (error != HDF_SUCCESS) { + return error; + } + cntlr->curDev->state.bits.uhs = 1; + } else { + /* highspeed dev set */ + error = SdHighSpeedDevInit(cntlr); + if (error != HDF_SUCCESS) { + return error; + } + } + + return SdDeviceAdd(cntlr); +} + +static int32_t SdDetect(struct MmcCntlr *cntlr) +{ + int32_t ret; + + HDF_LOGD("Detect sd dev start..."); + /* dev state: idle. */ + MmcGoIdleState(cntlr); + /* dev state: idle -> idle. */ + (void)SdCmdSendIfCond(cntlr, cntlr->ocrDef.ocrData); + /* Initialize SD. */ + ret = SdInit(cntlr); + if (ret == HDF_SUCCESS) { + HDF_LOGD("Detect sd dev success! %s dev at address 0x%x!", + cntlr->curDev->state.bits.uhs ? "Ultra high speed" : + (cntlr->curDev->state.bits.highSpeed ? "High speed" : ""), + cntlr->curDev->reg.rca); + } + return ret; +} + +static int32_t SdioSendOpCond(struct MmcCntlr *cntlr, uint32_t arg, uint32_t *ocr) +{ + struct MmcCmd cmd = {0}; + int32_t err; + uint32_t i; + + /* + * An SDIO aware host will send CMD5 prior to the CMD55/ACMD41 pair, and thus would receive a valid OCR in + * the R4 response to CMD5 and continue to initialize the card. + */ + cmd.cmdCode = SDIO_SEND_OP_COND; + /* [23:0] OCR; [24] S18R(Switching to 1.8V Request); [31:25] Stuff Bits. */ + cmd.argument = arg; + cmd.respType = MMC_RESP_R4 | MMC_CMD_TYPE_BCR; + for (i = 0; i < INIT_CMD_RETRY_TIMES; i++) { + err = MmcSendCmd(cntlr, &cmd, NULL, MMC_CMD_DEFAULT_RETRY_TIMES); + if (err != HDF_SUCCESS) { + break; + } + if (arg == 0) { + break; + } + if ((cmd.resp[0] & MMC_CARD_BUSY_STATUS) > 0) { + break; + } + + err = HDF_ERR_TIMEOUT; + OsalMDelay(10); + } + if (ocr != NULL) { + /* + * Response R4 in Sd mode: [23:0] OCR; [24] S18A; [26:25] Stuff Bits; + * [27] Memory Present; [30: 28] Number of I/O functions. + */ + *ocr = cmd.resp[0]; + } + + return err; +} + +static int32_t SdioRespR5Check(struct MmcCmd *cmd) +{ + if (cmd->resp[0] & SDIO_R5_ERROR) { + HDF_LOGE("R5: error!"); + return HDF_ERR_IO; + } + if (cmd->resp[0] & SDIO_R5_OUT_OF_RANGE) { + HDF_LOGE("R5: out of range error!"); + return HDF_ERR_INVALID_PARAM; + } + if (cmd->resp[0] & SDIO_R5_FUNCTION_NUMBER) { + HDF_LOGE("R5: func num error!"); + return HDF_ERR_INVALID_PARAM; + } + return HDF_SUCCESS; +} + +int32_t SdioRwDirect(struct MmcCntlr *cntlr, struct SdioCmdParam *param, uint8_t *out) +{ + struct MmcCmd cmd = {0}; + int32_t err; + + if (cntlr == NULL || param == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + /* + * The IO_RW_DIRECT is the simplest means to access a single register within the total 128K of register space + * in any I/O function, including the common I/O area (CIA). This command reads or writes 1 byte using only 1 + * command/response pair. A common use is to initialize registers or monitor status values for I/O functions. + */ + cmd.cmdCode = SDIO_RW_DIRECT; + /* [31] R/W flag. */ + cmd.argument = ((param->writeflag == true) ? 0x80000000 : 0x00000000); + /* [30:28] Function Number. */ + cmd.argument |= (param->funcNum << 28); + /* [25:9] Register Address. */ + cmd.argument |= (param->regAddr << 9); + /* [7:0] Write Data or Stuff Bits. */ + cmd.argument |= param->writeData; + cmd.respType = MMC_RESP_SPI_R5 | MMC_RESP_R5 | MMC_CMD_TYPE_AC; + err = MmcSendCmd(cntlr, &cmd, NULL, 1); + if (err != HDF_SUCCESS) { + return err; + } + + /* resp error check. */ + err = SdioRespR5Check(&cmd); + if (err != HDF_SUCCESS) { + return err; + } + if (out != NULL) { + *out = cmd.resp[0] & 0xFF; + } + return HDF_SUCCESS; +} + +int32_t SdioRwExtended(struct MmcCntlr *cntlr, struct SdioCmdParam *param, + uint8_t *buf, uint32_t blockNum, uint32_t blockSize) +{ + struct MmcCmd cmd = {0}; + struct MmcData data = {0}; + int32_t err; + + if (cntlr == NULL || param == NULL) { + return HDF_ERR_INVALID_PARAM; + } + /* Register Address: Start Address of I/O register to read or write. Range is [1FFFFh:0]. */ + if (param->regAddr != ((param->regAddr) & 0x1FFFF)) { + return HDF_ERR_INVALID_PARAM; + } + + cmd.cmdCode = SDIO_RW_EXTENDED; + /* [31] R/W flag. */ + cmd.argument = ((param->writeflag == true) ? 0x80000000 : 0x00000000); + /* [30:28] Function Number. */ + cmd.argument |= (param->funcNum << 28); + /* [26] Op Code. */ + cmd.argument |= ((param->incrAddrFlag == true) ? 0x04000000 : 0x00000000); + /* [25:9] Register Address. */ + cmd.argument |= (param->regAddr << 9); + /* + * [8:0] Byte/Block Count. + * If the command is operating on bytes(Block Mode = 0), this field contains the number of bytes + * to read or write. A value of 0 shall cause 512 bytes to be read or written. + * If the command is in block mode(Block Mode = 1), the Block Count field specifies the number + * of Data Blocks to be transferred following this command. + */ + if (blockNum == 1 && blockSize <= 512) { + cmd.argument |= ((blockSize == 512) ? 0 : blockSize); /* byte mode */ + } else { + /* [27] Block Mode. */ + cmd.argument |= (0x08000000 | blockNum); + } + cmd.respType = MMC_RESP_SPI_R5 | MMC_RESP_R5 | MMC_CMD_TYPE_ADTC; + + data.blockSize = blockSize; + data.blockNum = blockNum; + data.dataFlags = ((param->writeflag == true) ? DATA_WRITE : DATA_READ); + if (param->scatterFlag == false) { + data.dataBuffer = buf; + } else { + data.scatter = (void *)buf; + data.scatterLen = param->scatterLen; + } + + err = MmcSendCmd(cntlr, &cmd, &data, 1); + if (err != HDF_SUCCESS) { + return err; + } + + /* resp error check. */ + return SdioRespR5Check(&cmd); +} + +static void SdioIoReset(struct MmcCntlr *cntlr) +{ + struct SdioCmdParam param = {0}; + uint8_t out = 0; + int32_t error; + + /* + * In order to reset an I/O only card or the I/O portion of a combo card, + * use CMD52 to write a 1 to the RES bit in the CCCR(bit3 of register 6), + * because it can't issue CMD52 after CMD0. + */ + param.regAddr = IO_ABORT; + /* read register 6 of CCCR. */ + error = SdioRwDirect(cntlr, ¶m, &out); + if (error < 0) { + out = SDIO_CCCR_RES; + } else { + out |= SDIO_CCCR_RES; + } + /* write the RES bit to 1. */ + param.writeflag = true; + param.writeData = out; + (void)SdioRwDirect(cntlr, ¶m, NULL); +} + +int32_t SdioReadWriteByte(struct MmcCntlr *cntlr, bool writeFlag, + uint32_t funcNum, uint32_t addr, uint8_t *data) +{ + struct SdioCmdParam param = {0}; + + if (cntlr == NULL || data == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + param.regAddr = addr; + param.funcNum = funcNum; + if (writeFlag == true) { + param.writeflag = true; + param.writeData = *data; + return SdioRwDirect(cntlr, ¶m, NULL); + } + return SdioRwDirect(cntlr, ¶m, data); +} + +static int32_t SdioReadWriteRemainBytes(struct MmcCntlr *cntlr, struct SdioCmdParam *param, + uint8_t *data, uint32_t size, uint32_t addr) +{ + uint32_t maxBlkSize, curSize; + struct SdioDevice *dev = (struct SdioDevice *)cntlr->curDev; + uint32_t remLen = size; + uint32_t curAddr = addr; + uint8_t *buffer = data; + int32_t err; + + maxBlkSize = MMC_MIN(cntlr->maxBlkSize, dev->curFunction->maxBlkSize); + maxBlkSize = MMC_MIN(maxBlkSize, BYTES_PER_BLOCK); + if (maxBlkSize == 0) { + HDF_LOGE("max block size is invalid!"); + return HDF_ERR_INVALID_PARAM; + } + + while (remLen > 0) { + curSize = MMC_MIN(remLen, maxBlkSize); + param->regAddr = curAddr; + err = SdioRwExtended(cntlr, param, buffer, 1, curSize); + if (err != HDF_SUCCESS) { + HDF_LOGD("SdioReadWriteBlock: bytes mode, err = %d, addr = %d, curSize = %d!", err, addr, curSize); + return err; + } + buffer += curSize; + if (param->incrAddrFlag == true) { + curAddr += curSize; + } + remLen -= curSize; + } + return HDF_SUCCESS; +} + +static void SdioFillRwExtendedCmdParam(struct SdioCmdParam *param, + struct SdioDevice *dev, struct SdioRwBlockInfo *info) +{ + param->funcNum = dev->curFunction->funcNum; + param->incrAddrFlag = info->incrAddrFlag; + param->writeflag = info->writeFlag; + if (info->scatterFlag == true) { + param->scatterFlag = true; + param->scatterLen = info->scatterLen; + param->regAddr = info->addr; + } +} + +int32_t SdioReadWriteBlock(struct MmcCntlr *cntlr, struct SdioRwBlockInfo *info) +{ + uint32_t maxBlkNum, maxBlkSize, curblkNum, curSize, curAddr, remLen; + int32_t err; + struct SdioCmdParam param = {0}; + struct SdioDevice *dev = NULL; + uint8_t *buffer = NULL; + + if (cntlr == NULL || info == NULL) { + return HDF_ERR_INVALID_PARAM; + } + dev = (struct SdioDevice *)cntlr->curDev; + if (dev == NULL || dev->curFunction == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + maxBlkSize = MMC_MIN(cntlr->maxBlkSize, dev->curFunction->maxBlkSize); + maxBlkSize = MMC_MIN(maxBlkSize, BYTES_PER_BLOCK); + if (maxBlkSize == 0) { + return HDF_ERR_INVALID_PARAM; + } + if (dev->curFunction->curBlkSize == 0 || cntlr->maxBlkNum == 0) { + return HDF_ERR_INVALID_PARAM; + } + + remLen = info->size; + curAddr = info->addr; + buffer = info->buf; + SdioFillRwExtendedCmdParam(¶m, dev, info); + if (info->scatterFlag == true) { + return SdioRwExtended(cntlr, ¶m, buffer, MMC_MAX(1, remLen / maxBlkSize), MMC_MIN(remLen, maxBlkSize)); + } + /* send block. */ + if (dev->sdioReg.cccr.multiBlock > 0 && (remLen > maxBlkSize)) { + maxBlkNum = MMC_MIN((cntlr->maxReqSize / dev->curFunction->curBlkSize), cntlr->maxBlkNum); + maxBlkNum = MMC_MIN(maxBlkNum, SDIO_BLOCK_TRANSFER_MAX_BLKNUM); + while (remLen > dev->curFunction->curBlkSize) { + curblkNum = remLen / dev->curFunction->curBlkSize; + curblkNum = MMC_MIN(curblkNum, maxBlkNum); + curSize = curblkNum * dev->curFunction->curBlkSize; + param.regAddr = curAddr; + err = SdioRwExtended(cntlr, ¶m, buffer, curblkNum, dev->curFunction->curBlkSize); + if (err != HDF_SUCCESS) { + return err; + } + buffer += curSize; + if (info->incrAddrFlag == true) { + curAddr += curSize; + } + remLen -= curSize; + } + } + + /* send remaind bytes. */ + return SdioReadWriteRemainBytes(cntlr, ¶m, buffer, remLen, curAddr); +} + +static int32_t SdioCdDisable(struct MmcCntlr *cntlr) +{ + struct SdioCmdParam param = {0}; + int32_t error; + uint8_t ctrl; + + param.regAddr = BUS_INTERFACE_CONTROL; + /* read register 7 of CCCR. */ + error = SdioRwDirect(cntlr, ¶m, &ctrl); + if (error != HDF_SUCCESS) { + HDF_LOGE("SdioCdDisable: read BIC fail!"); + return error; + } + /* + * write the CD Disable bit to 1. + * This bit shall be set to 1 before issuing CMD53. + */ + ctrl |= SDIO_CCCR_CD_DISABLE; + param.writeflag = true; + param.writeData = ctrl; + return SdioRwDirect(cntlr, ¶m, NULL); +} + +static int32_t SdioReadCccrSdioRev(struct MmcCntlr *cntlr, struct SdioCccr *cccr, uint8_t *cccrRev) +{ + struct SdioCmdParam param = {0}; + int32_t err; + uint8_t data; + + /* read register 0 of CCCR. */ + param.regAddr = CCCR_SDIO_REVISION; + err = SdioRwDirect(cntlr, ¶m, &data); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdioReadCccrSdioRev: read sdio rev fail!"); + return err; + } + /* bit3-bit0: CCCR_REVISION */ + *cccrRev = data & 0x0f; + if ((*cccrRev) > SDIO_CCCR_VERSION_3_00) { + HDF_LOGE("SdioReadCccrSdioRev: cccr rev error!"); + return HDF_FAILURE; + } + /* bit7-bit4: SDIO_REVISION */ + cccr->sdioRev = (data & 0xf0) >> 4; + return HDF_SUCCESS; +} + +static int32_t SdioReadCccrCapbility(struct MmcCntlr *cntlr, struct SdioCccr *cccr) +{ + struct SdioCmdParam param = {0}; + int32_t error; + uint8_t cap; + + /* read register 8 of CCCR. */ + param.regAddr = CARD_CAPBILITY; + error = SdioRwDirect(cntlr, ¶m, &cap); + if (error != HDF_SUCCESS) { + HDF_LOGE("SdioReadCccrCapbility: read card cap fail!"); + return error; + } + + if ((cap & SDIO_CCCR_CAP_4BLS) > 0) { + cccr->lowSpeed4Bit = 1; + } + if ((cap & SDIO_CCCR_CAP_LSC) > 0) { + cccr->lowSpeed = 1; + } + if ((cap & SDIO_CCCR_CAP_SMB) > 0) { + cccr->multiBlock = 1; + } + return HDF_SUCCESS; +} + +static int32_t SdioReadCccrPowerControl(struct MmcCntlr *cntlr, struct SdioCccr *cccr) +{ + struct SdioCmdParam param = {0}; + int32_t error; + uint8_t ctrl; + + /* read register 18 of CCCR. */ + param.regAddr = POWER_CONTROL; + error = SdioRwDirect(cntlr, ¶m, &ctrl); + if (error != HDF_SUCCESS) { + HDF_LOGE("SdioReadCccrPowerControl: read power control fail!"); + return error; + } + + if ((ctrl & SDIO_CCCR_POWER_SMPC) > 0) { + cccr->highPower = 1; + } + return HDF_SUCCESS; +} + +static int32_t SdioReadCccrBusSpeed(struct MmcCntlr *cntlr, struct SdioCccr *cccr) +{ + struct SdioCmdParam param = {0}; + int32_t error; + uint8_t speed; + + /* read register 19 of CCCR. */ + param.regAddr = BUS_SPEED_SELECT; + error = SdioRwDirect(cntlr, ¶m, &speed); + if (error != HDF_SUCCESS) { + HDF_LOGE("SdioReadCccrBusSpeed: read bus speed select fail!"); + return error; + } + + if ((speed & SDIO_CCCR_BUS_SPEED_SHS) > 0) { + cccr->highSpeed = 1; + } + return HDF_SUCCESS; +} + +int32_t SdioReadCccrIoEnable(struct MmcCntlr *cntlr, uint8_t *val) +{ + struct SdioCmdParam param = {0}; + + if (cntlr == NULL || val == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + /* read register 2(IOEx) of CCCR. */ + param.regAddr = IO_ENABLE; + return SdioRwDirect(cntlr, ¶m, val); +} + +int32_t SdioCccrIoEnable(struct MmcCntlr *cntlr) +{ + struct SdioCmdParam param = {0}; + struct SdioDevice *dev = NULL; + int32_t err; + uint8_t data; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + dev = (struct SdioDevice *)cntlr->curDev; + if (dev == NULL || dev->curFunction == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + /* read register 2(IOEx) of CCCR. */ + param.regAddr = IO_ENABLE; + err = SdioRwDirect(cntlr, ¶m, &data); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdioCccrIoEnable: read io enable fail! err = %d.", err); + return err; + } + /* + * IOEx:Enable Function x. + * If this bit is reset to 0, the function is disable. If this bit is set to 1, the function is enabled to start + * its initialization. The complation of initialization is indicated in IORx. On power up or after a reset, the + * card shall reset this bit to 0. The host can also use IOEx as a per function reset for error recovery. The host + * sequence for a per function reset is to reset IOEx to 0, wait until IORx becomes 0 and then set IOEx to 1 again. + */ + data |= (1 << dev->curFunction->funcNum); + param.writeflag = true; + param.writeData = data; + /* write register 2(IOEx) of CCCR. */ + return SdioRwDirect(cntlr, ¶m, NULL); +} + +int32_t SdioCccrIoDisable(struct MmcCntlr *cntlr) +{ + struct SdioCmdParam param = {0}; + struct SdioDevice *dev = NULL; + int32_t err; + uint8_t data; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + dev = (struct SdioDevice *)cntlr->curDev; + if (dev == NULL || dev->curFunction == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + /* read register 2(IOEx) of CCCR. */ + param.regAddr = IO_ENABLE; + err = SdioRwDirect(cntlr, ¶m, &data); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdioCccrIoDisable: read io enable fail! err = %d.", err); + return err; + } + + data &= (~(1 << dev->curFunction->funcNum)); + param.writeflag = true; + param.writeData = data; + /* write register 2(IOEx) of CCCR. */ + return SdioRwDirect(cntlr, ¶m, NULL); +} + +int32_t SdioReadCccrIoReady(struct MmcCntlr *cntlr, uint8_t *val) +{ + struct SdioCmdParam param = {0}; + + if (cntlr == NULL || val == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + /* read register 3(IORx) of CCCR. */ + param.regAddr = IO_READY; + /* + * IORx: I/O Function x Ready. + * If this bit is set to 0, the function is not ready to operate. This may be caused by the function being + * disabled or not ready due to internal causes such as a built-in-self-test in progress. If this bit is set to 1, + * the function is ready to operate. On power up or after a reset, this bit shall be set to 0. + */ + return SdioRwDirect(cntlr, ¶m, val); +} + +int32_t SdioReadCccrIntPending(struct MmcCntlr *cntlr, uint8_t *val) +{ + struct SdioCmdParam param = {0}; + + if (cntlr == NULL || val == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + /* read register 5(INTx) of CCCR. */ + param.regAddr = INT_PENDING; + /* + * INTx: Interrupt Pending for Function x. + * If this bit is cleared to 0, this indicates that no Interrupts are pending from this function. + * If this bit is set to 1, then this function has Interrupt pending. + * Note that if the IENx or IENM bits are not set, the host cannot receive this pending Interrupt. + */ + return SdioRwDirect(cntlr, ¶m, val); +} + +int32_t SdioCccrIntEnable(struct MmcCntlr *cntlr) +{ + int32_t err; + uint8_t val; + struct SdioCmdParam param = {0}; + struct SdioDevice *dev = NULL; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + dev = (struct SdioDevice *)cntlr->curDev; + if (dev == NULL || dev->curFunction == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + /* read register 4 of CCCR. */ + param.regAddr = INT_ENABLE; + err = SdioRwDirect(cntlr, ¶m, &val); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdioCccrIntEnable: read int enable fail! err = %d.", err); + return err; + } + /* + * [0]IENM: Interrupt Enable Master. + * If this bit is cleared to 0, no interrupts from this card shall be sent to the host. + * If this bit is set to 1, then any function's interrupt shall be sent to the host. + */ + val |= 1; + /* + * [1-7]IENx:Interrupt Enable for Function x. + * If this bit is cleared to 0, any interrupt form this function shall not be sent to the host. + * If this bit is set to 1, function's interrupt shall be sent to the host if the IENM is also set to 1. + */ + val |= (1 << dev->curFunction->funcNum); + param.writeflag = true; + param.writeData = val; + /* write register 4 of CCCR. */ + return SdioRwDirect(cntlr, ¶m, NULL); +} + +int32_t SdioCccrIntDisable(struct MmcCntlr *cntlr) +{ + struct SdioDevice *dev = (struct SdioDevice *)cntlr->curDev; + struct SdioCmdParam param = {0}; + int32_t err; + uint8_t val; + + if (dev == NULL || dev->curFunction == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + /* read register 4 of CCCR. */ + param.regAddr = INT_ENABLE; + err = SdioRwDirect(cntlr, ¶m, &val); + if (err != HDF_SUCCESS) { + HDF_LOGE("SdioCccrIntDisable: read int enable fail! err = %d.", err); + return err; + } + /* clear the function's interrupt. */ + val &= (~(1U << dev->curFunction->funcNum)); + if ((val & 0xFE) == 0) { + val = 0; + } + param.writeflag = true; + param.writeData = val; + /* write register 4 of CCCR. */ + return SdioRwDirect(cntlr, ¶m, NULL); +} + +static int32_t SdioReadCccr(struct MmcCntlr *cntlr) +{ + int32_t ret; + uint8_t cccrRev; + struct SdioDevice *sdioDev = NULL; + struct SdioCccr *cccr = NULL; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + sdioDev = (struct SdioDevice *)cntlr->curDev; + cccr = &(sdioDev->sdioReg.cccr); + ret = SdioReadCccrSdioRev(cntlr, cccr, &cccrRev); + if (ret != HDF_SUCCESS) { + return ret; + } + ret = SdioReadCccrCapbility(cntlr, cccr); + if (ret != HDF_SUCCESS) { + return ret; + } + + if (cccrRev >= SDIO_CCCR_VERSION_1_10) { + ret = SdioReadCccrPowerControl(cntlr, cccr); + if (ret != HDF_SUCCESS) { + return ret; + } + } + /* SDIO version 1.20 cards indicate their support for High-Speed mode with the SHS bit in the CCCR. */ + if (cccrRev >= SDIO_CCCR_VERSION_1_20) { + ret = SdioReadCccrBusSpeed(cntlr, cccr); + } + return ret; +} + +static int32_t SdioBusSpeedSelect(struct MmcCntlr *cntlr, bool enableHighSpeed) +{ + struct SdioCmdParam param = {0}; + int32_t error; + uint8_t speed; + + /* read register 19 of CCCR. */ + param.regAddr = BUS_SPEED_SELECT; + error = SdioRwDirect(cntlr, ¶m, &speed); + if (error != HDF_SUCCESS) { + HDF_LOGE("SdioBusSpeedSelect: read bus speed select fail! err = %d.", error); + return error; + } + /* fill BSS0. */ + if (enableHighSpeed == true) { + speed |= SDIO_CCCR_BUS_SPEED_EHS; + } else { + speed &= (~SDIO_CCCR_BUS_SPEED_EHS); + } + /* write BSS0. */ + param.writeflag = true; + param.writeData = speed; + return SdioRwDirect(cntlr, ¶m, NULL); +} + +static int32_t SdioSwitchHighSpeed(struct MmcCntlr *cntlr) +{ + struct SdioDevice *sdioDev = NULL; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + sdioDev = (struct SdioDevice *)cntlr->curDev; + if (cntlr->caps.bits.highSpeed == 0 || sdioDev->sdioReg.cccr.highSpeed == 0) { + return HDF_ERR_NOT_SUPPORT; + } + return SdioBusSpeedSelect(cntlr, true); +} + +static int32_t SdioEnableHighSpeed(struct MmcCntlr *cntlr) +{ + int32_t err; + + err = SdioSwitchHighSpeed(cntlr); + if (cntlr->curDev->type == MMC_DEV_SDIO || err != HDF_SUCCESS) { + return err; + } + + /* COMBO card, need switch SD memory. */ + err = SdSwitchHighSpeed(cntlr); + if (err == HDF_SUCCESS) { + return err; + } + /* sd switch fail, need switch sdio to default speed. */ + if (SdioBusSpeedSelect(cntlr, false) != HDF_SUCCESS) { + HDF_LOGD("SdioEnableHighSpeed: switch sdio to default speed fail."); + } + return err; +} + +static int32_t SdioSetBusWidth(struct MmcCntlr *cntlr, uint8_t width) +{ + struct SdioCmdParam param = {0}; + int32_t error; + uint8_t data; + + /* read register 7 of CCCR. */ + param.regAddr = BUS_INTERFACE_CONTROL; + error = SdioRwDirect(cntlr, ¶m, &data); + if (error != HDF_SUCCESS) { + HDF_LOGE("SdioSetBusWidth: read BIC fail, error = %d!", error); + return error; + } + + data |= width; + /* write bit1-bit0: Bus Width. */ + param.writeflag = true; + param.writeData = data; + return SdioRwDirect(cntlr, ¶m, NULL); +} + +static int32_t SdioSwitch4BitBusWidth(struct MmcCntlr *cntlr) +{ + struct SdioDevice *sdioDev = NULL; + + if (cntlr == NULL || cntlr->curDev == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + sdioDev = (struct SdioDevice *)cntlr->curDev; + if (cntlr->caps.bits.cap4Bit == 0) { + return HDF_ERR_NOT_SUPPORT; + } + /* + * Note that Low-Speed SDIO cards support 4-bit transfer as an optipn. When communicating with a + * Low-Speed SDIO card, the host shall fist determine if the card supports 4-bit transfer prior to + * attempting to select that mode. + */ + if (sdioDev->sdioReg.cccr.lowSpeed > 0 && sdioDev->sdioReg.cccr.lowSpeed4Bit == 0) { + return HDF_ERR_NOT_SUPPORT; + } + return SdioSetBusWidth(cntlr, SDIO_CCCR_WIDTH_4BIT); +} + +static int32_t SdioEnable4BitBusWidth(struct MmcCntlr *cntlr) +{ + int32_t error; + struct SdDevice *dev = (struct SdDevice *)cntlr->curDev; + + /* + * For an SD memory card, the bus width for SD mode is set using ACMD6. + * For an SDIO card a write to the CCCR usingCMD52 is used to select bus width. + * In the case of a combo card, both selection methods exist. + */ + error = SdioSwitch4BitBusWidth(cntlr); + if (cntlr->curDev->type == MMC_DEV_SDIO || error != HDF_SUCCESS) { + return error; + } + + /* COMBO card, need switch SD memory. */ + if ((dev->reg.scr.sdBusWidths & SD_SCR_BUS_WIDTHS_4) > 0 && + (cntlr->caps.bits.cap4Bit > 0)) { + error = SdAcmdSetBusWidth(cntlr, BUS_WIDTH4); + } + + return error; +} + +static int32_t SdioReadCisTplField(struct MmcCntlr *cntlr, uint32_t addr, uint8_t *data) +{ + struct SdioCmdParam param = {0}; + + param.regAddr = addr; + return SdioRwDirect(cntlr, ¶m, data); +} + +static void SdioDecodeCisTplManfId(struct MmcCntlr *cntlr, struct SdioFunction *function, + struct SdioCisTuple *tuple) +{ + uint16_t vendorId, deviceId; + struct SdioDevice *dev = NULL; + + if (tuple->tplLink < SDIO_CIS_TPL_MANFID_MIN_SIZE) { + return; + } + + /* + * CISTPL_MANFID Field: bit00[TPL_CODE(20)], bit01[TPL_LINK(at least 4)], bit02-03[SDIO Card manufacturer code], + * bit04-05[manufacturer information(Part Number and /or Revision)]. + * bit02-03-->tplBody[0:1], bit04-05-->tplBody[2:3]. + */ + vendorId = (tuple->tplBody[1] << BITS_PER_BYTE) | tuple->tplBody[0]; + deviceId = (tuple->tplBody[3] << BITS_PER_BYTE) | tuple->tplBody[2]; + HDF_LOGD("Sdio vendorId = 0x%x, deviceId = 0x%x.", vendorId, deviceId); + /* function CISTPL_MANFID. */ + if (function != NULL) { + function->deviceId = deviceId; + function->vendorId = vendorId; + return; + } + + /* common CISTPL_MANFID. */ + dev = (struct SdioDevice *)cntlr->curDev; + dev->sdioReg.cis.deviceId = deviceId; + dev->sdioReg.cis.vendorId = vendorId; +} + +static void SdioDecodeCisTplFunceCommon(struct MmcCntlr *cntlr, struct SdioCisTuple *tuple) +{ + struct SdioDevice *dev = (struct SdioDevice *)cntlr->curDev; + const uint8_t value[16] = { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; + const uint32_t unit[8] = { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 }; + + if (tuple->tplLink < SDIO_CIS_TPL_FUNCE_COMMON_MIN_SIZE) { + return; + } + + /* + * CISTPL_FUNCE(common): bit00[TPL_CODE(22h)], bit01[TPL_LINK], bit02[TPLFE_TYPE(00h)], + * bit03-04[TPLFE_FN0_BLK_SIZE], bit05[TPLFE_MAX_TRAN_SPEED]. + * bit2-->tplBody[0], bit03-04-->tplBody[1:2], bit05-->tplBody[3]. + */ + dev->sdioReg.cis.blkSize = (tuple->tplBody[2] << BITS_PER_BYTE) | tuple->tplBody[1]; + + /* + * This byte indicates the maximum transfer rate per one data line during data transfer. This value applies to + * all functions in the SDIO card. This value shall be 25Mb/Sec(32h) for all Full-Speed SDIO card. The minimum + * value for Low-Speed SDIO cards shall be 400 Kb/Sec(48h). The format is identical to the TRAN_SPEED value stored + * in the CSD of SD memory cards. The maximum data transfer rate is coded according to the following method: + * Bits 2:0 contain the transfer rate unit coded as follows: + * 0=100kbit/s, 1=1Mbit/s, 2=10Mbit/s, 3=100Mbit/s, ... 7=reserved. + * Bits 6:3 contain the time value coded as follows: + * 0=reserved, 1=1.0, 2=1.2, 3=1.3, 4=1.5, 5=2.0, 6=2.5, 7=3.0, 8= 3.5, 9=4.0, A=4.5, B=5.0, C=5.5, D=6.0, E=7.0, + * F= 8.0. + * Bit 7 is reserved and shall be 0. + */ + dev->sdioReg.cis.maxDtr = unit[tuple->tplBody[3] & 7] * value[(tuple->tplBody[3] >> 3) & 15]; +} + +static void SdioDecodeCisTplFunceFunction(struct SdioFunction *function, struct SdioCisTuple *tuple) +{ + uint32_t minSize; + + /* Rev 1.0, TPL_LINK 28bytes; >Rev 1.0, TPL_LINK 42bytes. */ + minSize = (function->dev->sdioReg.cccr.sdioRev == SDIO_CCCR_SDIO_REV_1_00) ? + SDIO_CIS_TPL_FUNCE_FUNCTION_PC_MIN_SIZE : SDIO_CIS_TPL_FUNCE_FUNCTION_PC_MAX_SIZE; + if (tuple->tplLink < minSize) { + return; + } + + /* + * CISTPL_FUNCE(function): bit00[TPL_CODE(22h)], bit01[TPL_LINK], bit02[TPLFE_TYPE(01h)], + * bit0E-0F[TPLFE_MAX_BLK_SIZE], bit1E-1F[TPLFE_ENABLE_TIMEOUT_VAL]. + * bit2-->tplBody[0], bit0E-0F-->tplBody[12:13], bit1E-1F-->tplBody[28:29]. + */ + function->maxBlkSize = (tuple->tplBody[13] << BITS_PER_BYTE) | tuple->tplBody[12]; + + /* + * TPLFE_ENABLE_TIMEOUT_VAL is added in SDIO Rev 1.1. This 16-bit value indicates the function's required time-out + * value for coming ready after being enabled. This per-function value indicated the time a host should wait from + * asserting IOEx until expecting the card to indicate ready by asserting IORx. Different SDIO functions take + * different amounts of time to become raedy after being enabled due to different internal initialization + * requirements. The required time-out limit is in 10mS steps. If the card required no time-out, this field shall + * be set to 0000h. + */ + if (function->dev->sdioReg.cccr.sdioRev > SDIO_CCCR_SDIO_REV_1_00) { + function->timeOut = (tuple->tplBody[28] | (tuple->tplBody[29] << BITS_PER_BYTE)) * 10; + } else { + function->timeOut = SDIO_CIS_TPLFE_ENABLE_TIMEOUT_VAL_DEF; + } +} + +static void SdioDecodeCisTplFunce(struct MmcCntlr *cntlr, struct SdioFunction *function, + struct SdioCisTuple *tuple) +{ + /* + * The Function Extension Tuple provides standard information about the card(common) and each individual function. + * There shall be one CISTPL_FUNCE in each function's CIS. There are two versions of the CISTPL_FUNCE tuple, one + * for the common CIS(function 0) and a version uesd by the individual function's CIS(1-7). + */ + if (tuple->tplBody[0] == SDIO_CIS_TPL_FUNCE_COMMON) { + if (function != NULL) { + return; + } + SdioDecodeCisTplFunceCommon(cntlr, tuple); + return; + } + + if (tuple->tplBody[0] == SDIO_CIS_TPL_FUNCE_FUNCTION_PC) { + if (function == NULL) { + return; + } + SdioDecodeCisTplFunceFunction(function, tuple); + } +} + +static void SdioDecodeCisTplField(struct MmcCntlr *cntlr, struct SdioFunction *function, + struct SdioCisTuple *tuple) +{ + /* decode MANFID. */ + if (tuple->tplCode == SDIO_CIS_TPL_MANFID) { + SdioDecodeCisTplManfId(cntlr, function, tuple); + return; + } + /* decode FUNCE. */ + if (tuple->tplCode == SDIO_CIS_TPL_FUNCE) { + SdioDecodeCisTplFunce(cntlr, function, tuple); + } +} + +static int32_t SdioFillTplInfo(struct MmcCntlr *cntlr, struct SdioCisTuple *tuple, + uint32_t *addr, uint8_t tplCode, uint8_t tplLink) +{ + int32_t ret; + uint32_t i; + + tuple->tplCode = tplCode; + tuple->tplLink = tplLink; + /* read tuple body. */ + for (i = 0; i < tplLink; i++) { + (*addr)++; + ret = SdioReadCisTplField(cntlr, *addr, &(tuple->tplBody[i])); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioFillTplInfo: read tuple body fail, err = %d.", ret); + return ret; + } + } + return HDF_SUCCESS; +} + +static int32_t SdioDecodeCis(struct MmcCntlr *cntlr, struct SdioFunction *function, uint32_t cisStartAddr) +{ + int32_t ret = HDF_SUCCESS; + uint8_t tplCode, tplLink; + struct SdioCisTuple *tuple = NULL; + uint32_t addr = cisStartAddr; + + while (ret == HDF_SUCCESS) { + /* read TPL_CODE. */ + ret = SdioReadCisTplField(cntlr, addr, &tplCode); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioDecodeCis: read TPL_CODE fail, err = %d.", ret); + return ret; + } + if (tplCode == SDIO_CIS_TPL_END || tplCode == SDIO_CIS_TPL_NULL) { + return HDF_SUCCESS; + } + /* read TPL_LINK. */ + addr++; + ret = SdioReadCisTplField(cntlr, addr, &tplLink); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioDecodeCis: read TPL_LINK fail, err = %d.", ret); + return ret; + } + if (tplLink == SDIO_CIS_TPL_END) { + return HDF_SUCCESS; + } + /* If the link field is 0, the the tuple body is empty. */ + if (tplLink == SDIO_CIS_TPL_NULL) { + continue; + } + + tuple = (struct SdioCisTuple *)OsalMemCalloc(sizeof(*tuple) + tplLink); + if (tuple == NULL) { + HDF_LOGE("SdioDecodeCis: mem alloc fail!"); + return HDF_ERR_MALLOC_FAIL; + } + + ret = SdioFillTplInfo(cntlr, tuple, &addr, tplCode, tplLink); + if (ret != HDF_SUCCESS) { + OsalMemFree(tuple); + return ret; + } + /* decode. */ + SdioDecodeCisTplField(cntlr, function, tuple); + OsalMemFree(tuple); + tuple = NULL; + addr++; + } + return ret; +} + +static int32_t SdioReadCis(struct MmcCntlr *cntlr, struct SdioFunction *function) +{ + uint32_t funcNum, i, cisStartAddr; + uint8_t data; + int32_t ret; + struct SdioCmdParam param = {0}; + + if (function == NULL) { + funcNum = 0; + } else { + funcNum = function->funcNum; + } + + /* read CIS pointer. */ + cisStartAddr = 0; + for (i = 0; i < SDIO_CCCR_CIS_START_ADDR_BYTES; i++) { + /* read register 0xn09-0xn0B of FBR. */ + param.regAddr = SDIO_FBR_BASE_ADDR(funcNum) + SDIO_FBR_POINTER_CIS + i; + ret = SdioRwDirect(cntlr, ¶m, &data); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioReadCis: read CIS pointer fail, err = %d.", ret); + return ret; + } + cisStartAddr |= data << (i * BITS_PER_BYTE); + } + return SdioDecodeCis(cntlr, function, cisStartAddr); +} + +static int32_t SdioReadFbr(struct MmcCntlr *cntlr, struct SdioFunction *func) +{ + struct SdioCmdParam param = {0}; + int32_t error; + uint8_t data; + + /* read register 0xn00 of FBR. */ + param.regAddr = SDIO_FBR_BASE_ADDR(func->funcNum) + SDIO_FBR_STD_FUNCTION_INTERFACE_CODE; + error = SdioRwDirect(cntlr, ¶m, &data); + if (error != HDF_SUCCESS) { + HDF_LOGE("SdioReadFbr: read SFIC fail, err = %d.", error); + return error; + } + + /* bit3-bit0: Standard SDIO Function Interface Code. */ + data &= 0x0f; + if (data == SDIO_FBR_STD_SDIO_IF) { + /* read register 0xn01 of FBR. */ + param.regAddr = SDIO_FBR_BASE_ADDR(func->funcNum) + SDIO_FBR_EXT_STD_FUNCTION_INTERFACE_CODE; + error = SdioRwDirect(cntlr, ¶m, &data); + if (error != HDF_SUCCESS) { + HDF_LOGE("SdioReadFbr: read ESFIC fail, err = %d.", error); + return error; + } + } + + func->funcClass = data; + return HDF_SUCCESS; +} + +int32_t SdioSetFbrIoBlockSize(struct MmcCntlr *cntlr, uint32_t blkSize) +{ + struct SdioCmdParam param = {0}; + struct SdioDevice *dev = NULL; + int32_t ret; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + dev = (struct SdioDevice *)cntlr->curDev; + if (dev == NULL || dev->curFunction == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + /* write register 0xn10 of FBR. */ + param.regAddr = SDIO_FBR_BASE_ADDR(dev->curFunction->funcNum) + SDIO_FBR_IO_BLOCK_SIZE; + param.writeflag = true; + /* + * Function 1-7 I/O Block Size. + * This 16-bit register sets the block size for I/O block operations for each function(1-7). + * The maximum block size is 2048 and the minimum is 1. At power-up or reset, this register + * shall be initially loaded with a value of 0. The host is responsible for setting the appropriate + * value for the block size supported by each function. This pointer is stored in little-endian format. + */ + param.writeData = (blkSize & 0xff); + ret = SdioRwDirect(cntlr, ¶m, NULL); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioSetFbrIoBlockSize: write I/O Block Size fail, err = %d.", ret); + return ret; + } + + /* write register 0xn11 of FBR. */ + param.regAddr++; + param.writeData = ((blkSize >> BITS_PER_BYTE) & 0xff); + return SdioRwDirect(cntlr, ¶m, NULL); +} + +static uint32_t SdioGetMaxClock(struct MmcCntlr *cntlr) +{ + uint32_t clock; + struct MmcDevice *mmcDev = cntlr->curDev; + struct SdioDevice *sdioDev = (struct SdioDevice *)mmcDev; + + if (mmcDev->state.bits.highSpeed == 1) { + /* The card operates in High-Speed timing mode with a clock rate up to 50MHz. */ + clock = 50000000; + } else { + clock = sdioDev->sdioReg.cis.maxDtr; + } + + if (mmcDev->type == MMC_DEV_COMBO) { + clock = (clock < SdGetMaxClock(cntlr)) ? clock : SdGetMaxClock(cntlr); + } + + if (clock > cntlr->freqMax) { + clock = cntlr->freqMax; + } + return clock; +} + +static struct SdioFunction *SdioAllocFunction(struct SdioDevice *sdioDev, uint32_t funcNum) +{ + struct SdioFunction *function = NULL; + + function = (struct SdioFunction *)OsalMemCalloc(sizeof(struct SdioFunction)); + if (function == NULL) { + HDF_LOGE("SdioAllocFunction: alloc fail!"); + return NULL; + } + function->dev = sdioDev; + function->funcNum = funcNum; + return function; +} + +static void SdioDeleteFunction(struct SdioFunction *function) +{ + if (function == NULL) { + return; + } + OsalMemFree(function); +} + +static int32_t SdioAddFunctions(struct MmcCntlr *cntlr, uint32_t funcs) +{ + struct SdioDevice *sdioDev = (struct SdioDevice *)cntlr->curDev; + struct SdioFunction *function = NULL; + uint32_t i; + int32_t ret; + + sdioDev->functions = 0; + for (i = 0; i < funcs; i++) { + function = SdioAllocFunction(sdioDev, i + 1); + if (function == NULL) { + return HDF_ERR_MALLOC_FAIL; + } + ret = SdioReadFbr(cntlr, function); + if (ret != HDF_SUCCESS) { + return ret; + } + ret = SdioReadCis(cntlr, function); + if (ret != HDF_SUCCESS) { + SdioDeleteFunction(function); + return ret; + } + + if (function->vendorId == 0) { + function->vendorId = sdioDev->sdioReg.cis.vendorId; + function->deviceId = sdioDev->sdioReg.cis.deviceId; + } + /* A value of zero is not valid and shall not be used. */ + if (function->maxBlkSize == 0) { + function->maxBlkSize = sdioDev->sdioReg.cis.blkSize; + } + + sdioDev->sdioFunc[i] = function; + (sdioDev->functions)++; + } + return HDF_SUCCESS; +} + +static void SdioDelete(struct SdioDevice *sdioDev) +{ + uint32_t i; + + for (i = 0; i < sdioDev->functions; i++) { + SdioDeleteFunction(sdioDev->sdioFunc[i]); + sdioDev->sdioFunc[i] = NULL; + } +} + +static int32_t SdioDeviceAdd(struct MmcCntlr *cntlr) +{ + /* add dev. */ + if (MmcDeviceAdd(cntlr->curDev) != HDF_SUCCESS) { + HDF_LOGE("SdioDeviceAdd: Add device fail!"); + return HDF_FAILURE; + } + cntlr->curDev->state.bits.present = 1; + return HDF_SUCCESS; +} + +static int32_t SdioSelect(struct MmcCntlr *cntlr, uint32_t *rocr) +{ + int32_t error; + + /* cmd5, set the support voltage. */ + error = SdioSendOpCond(cntlr, cntlr->curDev->reg.ocr.ocrData, rocr); + if (error != HDF_SUCCESS) { + HDF_LOGE("cmd5(set voltage) fail, err = %d.", error); + return error; + } + + /* Judge Combo Card. */ + if (((*rocr) & SDIO_R4_MEMORY_PRESENT) > 0) { + if (SdSelect(cntlr, rocr) == 0) { + cntlr->curDev->type = MMC_DEV_COMBO; + HDF_LOGD("combo dev!!"); + } + } + /* get RCA. */ + error = SdCmdSendRelativeAddr(cntlr, &(cntlr->curDev->reg.rca)); + if (error != HDF_SUCCESS) { + HDF_LOGE("cmd3(get RCA) fail, err = %d.", error); + return error; + } + if (cntlr->curDev->type == MMC_DEV_COMBO) { + /* get CSD, CMD9 should send in stby. */ + error = SdReadCsd(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("combo dev, read csd fail, err = %d.", error); + return error; + } + } + /* select card. */ + error = MmcSelectCard(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("cmd7(select card) fail, err = %d.", error); + return error; + } + + error = SdioReadCccr(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("read cccr fail, err = %d.", error); + return error; + } + /* read common CIS. */ + error = SdioReadCis(cntlr, NULL); + if (error != HDF_SUCCESS) { + HDF_LOGE("SdioInit: read cis fail, err = %d.", error); + return error; + } + if (cntlr->curDev->type == MMC_DEV_COMBO) { + error = SdReadRegisters(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("combo dev, read registers fail, err = %d.", error); + MmcGoIdleState(cntlr); + cntlr->curDev->type = MMC_DEV_SDIO; + } + } + return HDF_SUCCESS; +} + +static int32_t SdioInit(struct MmcCntlr *cntlr) +{ + int32_t error; + union MmcOcr ocr = {0}; + + /* cmd5, detect sdio dev and get the voltage range. */ + error = SdioSendOpCond(cntlr, 0, &(ocr.ocrData)); + if (error != HDF_SUCCESS) { + HDF_LOGE("cmd5(detect sdio) fail, err = %d", error); + return error; + } + + MmcCntlrSelectWorkVoltage(cntlr, &ocr); + if (cntlr->curDev->reg.ocr.ocrData == 0) { + HDF_LOGE("SdioInit: ocr is invalid!"); + return HDF_ERR_INVALID_PARAM; + } + + error = SdioSelect(cntlr, &(ocr.ocrData)); + if (error != HDF_SUCCESS) { + return error; + } + + error = SdioCdDisable(cntlr); + if (error != HDF_SUCCESS) { + HDF_LOGE("Cd disable fail, err = %d.", error); + return error; + } + error = SdioEnableHighSpeed(cntlr); + if (error == HDF_SUCCESS) { + cntlr->curDev->state.bits.highSpeed = 1; + MmcCntlrSetBusTiming(cntlr, BUS_TIMING_SD_HS); + } else if (error != HDF_ERR_NOT_SUPPORT) { + HDF_LOGE("Enable HS fail, err = %d.", error); + return error; + } + MmcCntlrSetClock(cntlr, SdioGetMaxClock(cntlr)); + + error = SdioEnable4BitBusWidth(cntlr); + if (error == HDF_SUCCESS) { + MmcCntlrSetBusWidth(cntlr, BUS_WIDTH4); + } else if (error != HDF_ERR_NOT_SUPPORT) { + HDF_LOGE("Enable 4-bits bus width fail, err = %d.", error); + return error; + } + /* R4, [30: 28] Number of I/O functions. */ + error = SdioAddFunctions(cntlr, ((ocr.ocrData >> 28) & SDIO_MAX_FUNCTION_NUMBER)); + if (error != HDF_SUCCESS) { + HDF_LOGE("Add functions fail, err = %d.", error); + return error; + } + + return SdioDeviceAdd(cntlr); +} + +int32_t SdioReinit(struct MmcCntlr *cntlr) +{ + union MmcOcr ocr = {0}; + int error; + + MmcGoIdleState(cntlr); + MmcCntlrSetClock(cntlr, cntlr->freqMin); + + /* cmd5, detect sdio dev and get the voltage range. */ + error = SdioSendOpCond(cntlr, 0, &(ocr.ocrData)); + if (error != HDF_SUCCESS) { + return error; + } + /* cmd5, set the support voltage. */ + error = SdioSendOpCond(cntlr, cntlr->curDev->reg.ocr.ocrData, &(ocr.ocrData)); + if (error != HDF_SUCCESS) { + return error; + } + /* get RCA. */ + error = SdCmdSendRelativeAddr(cntlr, &(cntlr->curDev->reg.rca)); + if (error != HDF_SUCCESS) { + return error; + } + /* select card. */ + error = MmcSelectCard(cntlr); + if (error != HDF_SUCCESS) { + return error; + } + error = SdioEnableHighSpeed(cntlr); + if (error != HDF_SUCCESS) { + return error; + } + MmcCntlrSetClock(cntlr, SdioGetMaxClock(cntlr)); + + error = SdioEnable4BitBusWidth(cntlr); + if (error == HDF_SUCCESS) { + MmcCntlrSetBusWidth(cntlr, BUS_WIDTH4); + } + return error; +} + +static int32_t SdioDetect(struct MmcCntlr *cntlr) +{ + int32_t err; + + HDF_LOGD("Detect sdio dev start..."); + /* + * After reset or power-up, all I/O functions on the card are disabled and the I/O portion of the card shall + * not execute any operation except CMD5 or CMD0. If there is SD memory on the card, that memory shall + * respond normally to all mandatory memory commands. + */ + SdioIoReset(cntlr); + MmcGoIdleState(cntlr); + /* Initialize SDIO. */ + err = SdioInit(cntlr); + if (err == HDF_SUCCESS) { + HDF_LOGD("Detect sdio dev success! %s dev at address 0x%x!", + cntlr->curDev->state.bits.highSpeed ? "High speed" : "", cntlr->curDev->reg.rca); + return HDF_SUCCESS; + } + SdioDelete((struct SdioDevice *)cntlr->curDev); + return err; +} + +void MmcDeleteDev(struct MmcCntlr *cntlr) +{ + if (cntlr == NULL || cntlr->curDev == NULL) { + return; + } + + if (cntlr->curDev->state.bits.present == 0) { + return; + } + cntlr->curDev->state.bits.present = 0; + + if (cntlr->curDev->type == MMC_DEV_SDIO || cntlr->curDev->type == MMC_DEV_COMBO) { + SdioDelete((struct SdioDevice *)cntlr->curDev); + } + + MmcDeviceRemove(cntlr->curDev); + MmcCntlrFreeDev(cntlr); +} + +int32_t MmcDoDetect(struct MmcCntlr *cntlr) +{ + int32_t error; + enum MmcDevType devType; + + if (cntlr == NULL) { + return HDF_ERR_INVALID_PARAM; + } + devType = (enum MmcDevType)cntlr->devType; + if (devType >= MMC_DEV_COMBO) { + return HDF_ERR_INVALID_PARAM; + } + + if (MmcCntlrAllocDev(cntlr, devType) != HDF_SUCCESS) { + return HDF_ERR_INVALID_PARAM; + } + + MmcCntlrPowerUp(cntlr); + if (devType == MMC_DEV_SDIO) { + error = SdioDetect(cntlr); + } else if (devType == MMC_DEV_SD) { + error = SdDetect(cntlr); + } else { + error = EmmcDetect(cntlr); + } + + if (error == HDF_SUCCESS) { + HDF_LOGD("MmcDoDetect: host%d detect succ!", cntlr->index); + return error; + } + + HDF_LOGD("MmcDoDetect: host%d detect fail!", cntlr->index); + MmcCntlrFreeDev(cntlr); + MmcCntlrPowerOff(cntlr); + return error; +} diff --git a/support/platform/src/mmc/mmc_sdio.c b/support/platform/src/mmc/mmc_sdio.c new file mode 100644 index 00000000..9c39e7f5 --- /dev/null +++ b/support/platform/src/mmc/mmc_sdio.c @@ -0,0 +1,757 @@ +/* + * 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 "mmc_sdio.h" + +#define HDF_LOG_TAG mmc_sdio_c +#define SDIO_READ_IO_READY_RETRY_TIMES 10000 + +static int32_t SdioDeviceDefaultIncrAddrReadBytes(struct SdioDevice *dev, + uint8_t *data, uint32_t addr, uint32_t size) +{ + struct SdioFunction *func = dev->curFunction; + struct MmcCntlr *cntlr = NULL; + struct SdioRwBlockInfo info = {0}; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultIncrAddrReadBytes fail, func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (data == NULL) { + HDF_LOGE("SdioDeviceDefaultIncrAddrReadBytes fail, data is null."); + return HDF_ERR_INVALID_PARAM; + } + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultIncrAddrReadBytes fail, cntlr is null."); + return HDF_ERR_INVALID_OBJECT; + } + + if (size == 1) { + return SdioReadWriteByte(cntlr, false, func->funcNum, addr, data); + } else if (size > 1) { + info.addr = addr; + info.buf = data; + info.incrAddrFlag = true; + info.size = size; + info.writeFlag = false; + return SdioReadWriteBlock(cntlr, &info); + } + HDF_LOGE("SdioDeviceDefaultIncrAddrReadBytes fail, data size is 0."); + return HDF_ERR_INVALID_PARAM; +} + +static int32_t SdioDeviceDefaultIncrAddrWriteBytes(struct SdioDevice *dev, + uint8_t *data, uint32_t addr, uint32_t size) +{ + struct SdioFunction *func = dev->curFunction; + struct MmcCntlr *cntlr = NULL; + struct SdioRwBlockInfo info = {0}; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultIncrAddrWriteBytes fail, func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (data == NULL) { + HDF_LOGE("SdioDeviceDefaultIncrAddrWriteBytes fail, data is null."); + return HDF_ERR_INVALID_PARAM; + } + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultIncrAddrWriteBytes fail, cntlr is null."); + return HDF_ERR_INVALID_OBJECT; + } + + if (size == 1) { + return SdioReadWriteByte(cntlr, true, func->funcNum, addr, data); + } else if (size > 1) { + info.addr = addr; + info.buf = data; + info.incrAddrFlag = true; + info.size = size; + info.writeFlag = true; + return SdioReadWriteBlock(cntlr, &info); + } + HDF_LOGE("SdioDeviceDefaultIncrAddrWriteBytes fail, data size is 0."); + return HDF_ERR_INVALID_PARAM; +} + +static int32_t SdioDeviceDefaultFixedAddrReadBytes(struct SdioDevice *dev, + uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen) +{ + struct SdioFunction *func = dev->curFunction; + struct MmcCntlr *cntlr = NULL; + struct SdioRwBlockInfo info = {0}; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultFixedAddrReadBytes fail, func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (data == NULL || size == 0) { + HDF_LOGE("SdioDeviceDefaultFixedAddrReadBytes fail, param is invalid."); + return HDF_ERR_INVALID_PARAM; + } + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultFixedAddrReadBytes fail, cntlr is null."); + return HDF_ERR_INVALID_OBJECT; + } + + info.addr = addr; + info.buf = data; + info.incrAddrFlag = false; + info.size = size; + info.writeFlag = false; + if (scatterLen > 0) { + info.scatterFlag = true; + info.scatterLen = scatterLen; + } + return SdioReadWriteBlock(cntlr, &info); +} + +static int32_t SdioDeviceDefaultFixedAddrWriteBytes(struct SdioDevice *dev, + uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen) +{ + struct SdioFunction *func = dev->curFunction; + struct MmcCntlr *cntlr = NULL; + struct SdioRwBlockInfo info = {0}; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultFixedAddrWriteBytes fail, func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (data == NULL || size == 0) { + HDF_LOGE("SdioDeviceDefaultFixedAddrWriteBytes fail, param is invalid."); + return HDF_ERR_INVALID_PARAM; + } + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultFixedAddrWriteBytes fail, cntlr is null."); + return HDF_ERR_INVALID_OBJECT; + } + + info.addr = addr; + info.buf = data; + info.incrAddrFlag = false; + info.size = size; + info.writeFlag = true; + if (scatterLen > 0) { + info.scatterFlag = true; + info.scatterLen = scatterLen; + } + return SdioReadWriteBlock(cntlr, &info); +} + +static int32_t SdioDeviceDefaultFunc0ReadBytes(struct SdioDevice *dev, + uint8_t *data, uint32_t addr, uint32_t size) +{ + struct SdioFunction *func = dev->curFunction; + struct MmcCntlr *cntlr = NULL; + uint32_t i; + int32_t ret; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultFunc0ReadBytes fail, func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (data == NULL) { + HDF_LOGE("SdioDeviceDefaultFunc0ReadBytes fail, data is null."); + return HDF_ERR_INVALID_PARAM; + } + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultFunc0ReadBytes fail, cntlr is null."); + return HDF_ERR_INVALID_OBJECT; + } + + for (i = 0; i < size; i++) { + ret = SdioReadWriteByte(cntlr, false, 0, (addr + i), &data[i]); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioDeviceDefaultFunc0ReadBytes fail, i = %d.", i); + return ret; + } + } + return HDF_SUCCESS; +} + +static int32_t SdioDeviceDefaultFunc0WriteBytes(struct SdioDevice *dev, + uint8_t *data, uint32_t addr, uint32_t size) +{ + struct SdioFunction *func = dev->curFunction; + struct MmcCntlr *cntlr = NULL; + int32_t ret; + uint32_t i; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultFunc0WriteBytes fail, func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (data == NULL) { + HDF_LOGE("SdioDeviceDefaultFunc0WriteBytes fail, data is null."); + return HDF_ERR_INVALID_PARAM; + } + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultFunc0WriteBytes fail, cntlr is null."); + return HDF_ERR_INVALID_OBJECT; + } + + for (i = 0; i < size; i++) { + ret = SdioReadWriteByte(cntlr, true, 0, (addr + i), &data[i]); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioDeviceDefaultFunc0WriteBytes fail, i = %d.", i); + return ret; + } + } + return HDF_SUCCESS; +} + +static int32_t SdioDeviceDefaultSetBlockSize(struct SdioDevice *dev, uint32_t blkSize) +{ + struct SdioFunction *func = dev->curFunction; + struct MmcCntlr *cntlr = NULL; + uint32_t blockSize = blkSize; + int32_t ret; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultSetBlockSize: func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + cntlr = dev->sd.mmc.cntlr; + if (blockSize == 0) { + blockSize = ((func->maxBlkSize < cntlr->maxBlkSize) ? func->maxBlkSize : cntlr->maxBlkSize); + } + blockSize = MMC_MIN(blockSize, MMC_SEC_SIZE); + + ret = SdioSetFbrIoBlockSize(cntlr, blockSize); + if (ret == HDF_SUCCESS) { + func->curBlkSize = blockSize; + } + return ret; +} + +static int32_t SdioDeviceDefaultGetCommonInfo(struct SdioDevice *dev, + SdioCommonInfo *info, SdioCommonInfoType infoType) +{ + struct MmcCntlr *cntlr = NULL; + struct SdioFunction *func = dev->curFunction; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultGetCommonInfo: func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (info == NULL) { + HDF_LOGE("SdioDeviceDefaultGetCommonInfo: info is null."); + return HDF_ERR_INVALID_PARAM; + } + if (infoType != SDIO_FUNC_INFO) { + HDF_LOGE("SdioDeviceDefaultGetCommonInfo: cur type %d is not support.", infoType); + return HDF_ERR_NOT_SUPPORT; + } + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultGetCommonInfo fail, cntlr is null."); + return HDF_ERR_INVALID_PARAM; + } + info->funcInfo.enTimeout = func->timeOut; + info->funcInfo.maxBlockNum = cntlr->maxBlkNum; + info->funcInfo.maxBlockSize = cntlr->maxBlkSize; + info->funcInfo.maxRequestSize = cntlr->maxReqSize; + info->funcInfo.funcNum = func->funcNum; + info->funcInfo.irqCap = cntlr->caps.bits.sdioIrq; + info->funcInfo.data = (void *)func; + return HDF_SUCCESS; +} + +static int32_t SdioDeviceDefaultSetCommonInfo(struct SdioDevice *dev, + SdioCommonInfo *info, SdioCommonInfoType infoType) +{ + struct MmcCntlr *cntlr = NULL; + struct SdioFunction *func = dev->curFunction; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultSetCommonInfo: func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (info == NULL) { + HDF_LOGE("SdioDeviceDefaultSetCommonInfo: info is null."); + return HDF_ERR_INVALID_PARAM; + } + if (infoType != SDIO_FUNC_INFO) { + HDF_LOGE("SdioDeviceDefaultSetCommonInfo: cur type %d is not support.", infoType); + return HDF_ERR_NOT_SUPPORT; + } + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultSetCommonInfo fail, cntlr is null."); + return HDF_ERR_INVALID_PARAM; + } + + func->timeOut = info->funcInfo.enTimeout; + cntlr->maxBlkNum = info->funcInfo.maxBlockNum; + cntlr->maxBlkSize = info->funcInfo.maxBlockSize; + cntlr->maxReqSize = info->funcInfo.maxRequestSize; + func->funcNum = info->funcInfo.funcNum; + return HDF_SUCCESS; +} + +static int32_t SdioDeviceDefaultFlushData(struct SdioDevice *dev) +{ + struct MmcCntlr *cntlr = NULL; + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultFlushData fail, cntlr is null."); + return HDF_ERR_INVALID_OBJECT; + } + return SdioReinit(cntlr); +} + +static int32_t SdioDeviceDefaultEnableFunc(struct SdioDevice *dev) +{ + struct SdioFunction *func = dev->curFunction; + int32_t ret; + uint32_t i; + uint8_t val; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultEnableFunc: func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + ret = SdioCccrIoEnable(dev->sd.mmc.cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioDeviceDefaultEnableFunc: Io Enable fail."); + return ret; + } + + for (i = 0; i < SDIO_READ_IO_READY_RETRY_TIMES; i++) { + ret = SdioReadCccrIoReady(dev->sd.mmc.cntlr, &val); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioDeviceDefaultEnableFunc: read Io Ready fail."); + return ret; + } + if ((val & (1 << func->funcNum)) > 0) { + return HDF_SUCCESS; + } + } + + HDF_LOGE("SdioDeviceDefaultEnableFunc: Io not Ready."); + return HDF_ERR_TIMEOUT; +} + +static int32_t SdioDeviceDefaultDisableFunc(struct SdioDevice *dev) +{ + struct SdioFunction *func = dev->curFunction; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultDisableFunc: func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + return SdioCccrIoDisable(dev->sd.mmc.cntlr); +} + +static int32_t SdioDeviceDefaultClaimIrq(struct SdioDevice *dev, SdioIrqHandler *irqHandler) +{ + struct SdioFunction *func = dev->curFunction; + struct MmcCntlr *cntlr = NULL; + int32_t ret; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultClaimIrq: func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (func->irqHandler != NULL) { + HDF_LOGE("SdioDeviceDefaultClaimIrq: irq has been registered."); + return HDF_ERR_DEVICE_BUSY; + } + if (irqHandler == NULL) { + HDF_LOGE("SdioDeviceDefaultClaimIrq: irqHandler is NULL."); + return HDF_ERR_INVALID_PARAM; + } + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultClaimIrq: cntlr is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + ret = SdioCccrIntEnable(cntlr); + if (ret != HDF_SUCCESS) { + return ret; + } + + func->irqHandler = irqHandler; + if (cntlr->caps.bits.sdioIrq > 0) { + ret = MmcCntlrCreatSdioIrqThread(cntlr); + } + return ret; +} + +static int32_t SdioDeviceDefaultReleaseIrq(struct SdioDevice *dev) +{ + struct SdioFunction *func = dev->curFunction; + struct MmcCntlr *cntlr = NULL; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultReleaseIrq: func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultReleaseIrq: cntlr is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + if (func->irqHandler != NULL) { + func->irqHandler = NULL; + MmcCntlrDestroySdioIrqThread(cntlr); + } + if (cntlr->caps.bits.sdioIrq > 0 && cntlr->ops != NULL && cntlr->ops->setSdioIrq != NULL) { + (void)cntlr->ops->setSdioIrq(cntlr, false); + } + return SdioCccrIntDisable(cntlr); +} + +static int32_t SdioDeviceDefaultFindFunc(struct SdioDevice *dev, struct SdioFunctionConfig *cfg) +{ + uint32_t i; + struct SdioFunction *func = NULL; + + if (dev->functions > SDIO_MAX_FUNCTION_NUMBER) { + HDF_LOGE("SdioDeviceDefaultFindFunc: functions = %d, error!", dev->functions); + return HDF_ERR_INVALID_PARAM; + } + + for (i = 0; i < dev->functions; i++) { + func = dev->sdioFunc[i]; + if (func == NULL) { + continue; + } + if (cfg->deviceId == func->deviceId && + cfg->vendorId == func->vendorId && + cfg->funcNr == func->funcNum) { + dev->curFunction = func; + return HDF_SUCCESS; + } + } + + HDF_LOGE("SdioDeviceDefaultFindFunc: find func fail!"); + return HDF_FAILURE; +} + +static int32_t SdioDeviceDefaultClaimHost(struct SdioDevice *dev) +{ + struct SdioFunction *func = dev->curFunction; + struct MmcCntlr *cntlr = NULL; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultClaimHost: func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultClaimHost: cntlr is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + MmcCntlrLock(cntlr); + return HDF_SUCCESS; +} + +static int32_t SdioDeviceDefaultReleaseHost(struct SdioDevice *dev) +{ + struct SdioFunction *func = dev->curFunction; + struct MmcCntlr *cntlr = NULL; + + if (func == NULL) { + HDF_LOGE("SdioDeviceDefaultReleaseHost: func is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + cntlr = dev->sd.mmc.cntlr; + if (cntlr == NULL) { + HDF_LOGE("SdioDeviceDefaultReleaseHost: cntlr is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + MmcCntlrUnlock(cntlr); + return HDF_SUCCESS; +} + +static struct SdioDeviceOps g_sdioDefaultOps = { + .incrAddrReadBytes = SdioDeviceDefaultIncrAddrReadBytes, + .incrAddrWriteBytes = SdioDeviceDefaultIncrAddrWriteBytes, + .fixedAddrReadBytes = SdioDeviceDefaultFixedAddrReadBytes, + .fixedAddrWriteBytes = SdioDeviceDefaultFixedAddrWriteBytes, + .func0ReadBytes = SdioDeviceDefaultFunc0ReadBytes, + .func0WriteBytes = SdioDeviceDefaultFunc0WriteBytes, + .setBlockSize = SdioDeviceDefaultSetBlockSize, + .getCommonInfo = SdioDeviceDefaultGetCommonInfo, + .setCommonInfo = SdioDeviceDefaultSetCommonInfo, + .flushData = SdioDeviceDefaultFlushData, + .enableFunc = SdioDeviceDefaultEnableFunc, + .disableFunc = SdioDeviceDefaultDisableFunc, + .claimIrq = SdioDeviceDefaultClaimIrq, + .releaseIrq = SdioDeviceDefaultReleaseIrq, + .findFunc = SdioDeviceDefaultFindFunc, + .claimHost = SdioDeviceDefaultClaimHost, + .releaseHost = SdioDeviceDefaultReleaseHost, +}; + +int32_t SdioDeviceFindFunction(struct SdioDevice *sdio, struct SdioFunctionConfig *config) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceFindFunction: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->findFunc == NULL) { + HDF_LOGE("SdioDeviceFindFunction: func is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->findFunc(sdio, config); +} + +int32_t SdioDeviceIncrAddrReadBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceIncrAddrReadBytes: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->incrAddrReadBytes == NULL) { + HDF_LOGE("SdioDeviceIncrAddrReadBytes: incrAddrReadBytes is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->incrAddrReadBytes(sdio, data, addr, size); +} + +int32_t SdioDeviceIncrAddrWriteBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceIncrAddrWriteBytes: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->incrAddrWriteBytes == NULL) { + HDF_LOGE("SdioDeviceIncrAddrWriteBytes: incrAddrWriteBytes is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->incrAddrWriteBytes(sdio, data, addr, size); +} + +int32_t SdioDeviceFixedAddrReadBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceFixedAddrReadBytes: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->fixedAddrReadBytes == NULL) { + HDF_LOGE("SdioDeviceFixedAddrReadBytes: fixedAddrReadBytes is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->fixedAddrReadBytes(sdio, data, addr, size, scatterLen); +} + +int32_t SdioDeviceFixedAddrWriteBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceFixedAddrWriteBytes: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->fixedAddrWriteBytes == NULL) { + HDF_LOGE("SdioDeviceFixedAddrWriteBytes: fixedAddrWriteBytes is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->fixedAddrWriteBytes(sdio, data, addr, size, scatterLen); +} + +int32_t SdioDeviceFunc0ReadBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceFunc0ReadBytes: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->func0ReadBytes == NULL) { + HDF_LOGE("SdioDeviceFunc0ReadBytes: func0ReadBytes is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->func0ReadBytes(sdio, data, addr, size); +} + +int32_t SdioDeviceFunc0WriteBytes(struct SdioDevice *sdio, + uint8_t *data, uint32_t addr, uint32_t size) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceFunc0WriteBytes: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->func0WriteBytes == NULL) { + HDF_LOGE("SdioDeviceFunc0WriteBytes: func0WriteBytes is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->func0WriteBytes(sdio, data, addr, size); +} + +int32_t SdioDeviceSetBlockSize(struct SdioDevice *sdio, uint32_t blockSize) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceSetBlockSize: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->setBlockSize == NULL) { + HDF_LOGE("SdioDeviceSetBlockSize: setBlockSize is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->setBlockSize(sdio, blockSize); +} + +int32_t SdioDeviceGetCommonInfo(struct SdioDevice *sdio, + SdioCommonInfo *info, SdioCommonInfoType infoType) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceGetCommonInfo: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->getCommonInfo == NULL) { + HDF_LOGE("SdioDeviceGetCommonInfo: getCommonInfo is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->getCommonInfo(sdio, info, infoType); +} + +int32_t SdioDeviceSetCommonInfo(struct SdioDevice *sdio, + SdioCommonInfo *info, SdioCommonInfoType infoType) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceSetCommonInfo: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->setCommonInfo == NULL) { + HDF_LOGE("SdioDeviceSetCommonInfo: setCommonInfo is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->setCommonInfo(sdio, info, infoType); +} + +int32_t SdioDeviceFlushData(struct SdioDevice *sdio) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceFlushData: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->flushData == NULL) { + HDF_LOGE("SdioDeviceFlushData: flushData is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->flushData(sdio); +} + +int32_t SdioDeviceClaimHost(struct SdioDevice *sdio) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceClaimHost: cntlr is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + if (sdio->sdioOps->claimHost != NULL) { + return sdio->sdioOps->claimHost(sdio); + } + return HDF_SUCCESS; +} + +int32_t SdioDeviceReleaseHost(struct SdioDevice *sdio) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceReleaseHost: cntlr is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + + if (sdio->sdioOps->releaseHost != NULL) { + return sdio->sdioOps->releaseHost(sdio); + } + return HDF_SUCCESS; +} + +int32_t SdioDeviceEnableFunc(struct SdioDevice *sdio) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceEnableFunc: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->enableFunc == NULL) { + HDF_LOGE("SdioDeviceEnableFunc: enableFunc is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->enableFunc(sdio); +} + +int32_t SdioDeviceDisableFunc(struct SdioDevice *sdio) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceDisableFunc: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->disableFunc == NULL) { + HDF_LOGE("SdioDeviceDisableFunc: disableFunc is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->disableFunc(sdio); +} + +int32_t SdioDeviceClaimIrq(struct SdioDevice *sdio, SdioIrqHandler *irqHandler) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceClaimIrq: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->claimIrq == NULL) { + HDF_LOGE("SdioDeviceClaimIrq: claimIrq is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->claimIrq(sdio, irqHandler); +} + +int32_t SdioDeviceReleaseIrq(struct SdioDevice *sdio) +{ + if (sdio->sdioOps == NULL) { + HDF_LOGE("SdioDeviceReleaseIrq: ops is NULL."); + return HDF_ERR_INVALID_OBJECT; + } + if (sdio->sdioOps->releaseIrq == NULL) { + HDF_LOGE("SdioDeviceReleaseIrq: releaseIrq is NULL."); + return HDF_FAILURE; + } + return sdio->sdioOps->releaseIrq(sdio); +} + +void SdioDeviceAddOps(struct SdioDevice *sdio, void *ops) +{ + if (sdio == NULL) { + HDF_LOGE("SdioDeviceAddOps: sdio is NULL."); + return; + } + if (ops == NULL) { + sdio->sdioOps = &g_sdioDefaultOps; + HDF_LOGD("SdioDeviceAddOps: use default ops."); + } else { + sdio->sdioOps = (struct SdioDeviceOps *)ops; + } +} diff --git a/support/platform/src/mmc/sdio_if.c b/support/platform/src/mmc/sdio_if.c new file mode 100644 index 00000000..cd05ef45 --- /dev/null +++ b/support/platform/src/mmc/sdio_if.c @@ -0,0 +1,336 @@ +/* + * 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 "sdio_if.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "mmc_sdio.h" +#include "osal_mem.h" +#include "securec.h" + +#define HDF_LOG_TAG sdio_if_c + +static int32_t SdioDeviceGetFromHandle(DevHandle handle, struct SdioDevice **sdio) +{ + struct MmcDevice *mmc = NULL; + + if (handle == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + if (sdio == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + mmc = MmcCntlrGetDevice((struct MmcCntlr *)handle); + if (mmc == NULL) { + return HDF_PLT_ERR_NO_DEV; + } + if (mmc->type != MMC_DEV_SDIO && mmc->type != MMC_DEV_COMBO) { + MmcDevicePut(mmc); + return HDF_PLT_ERR_DEV_TYPE; + } + + *sdio = (struct SdioDevice *)mmc; + return HDF_SUCCESS; +} + +DevHandle SdioOpen(int16_t mmcBusNum, struct SdioFunctionConfig *config) +{ + int32_t ret; + struct MmcCntlr *cntlr = NULL; + struct SdioDevice *sdio = NULL; + DevHandle handle = NULL; + + if (config == NULL) { + HDF_LOGE("SdioOpen: config can't be null!"); + return NULL; + } + + handle = MmcOpen(mmcBusNum); + if (handle == NULL) { + HDF_LOGE("SdioOpen: SdioGetCntlrByBusNum fail!"); + return NULL; + } + cntlr = (struct MmcCntlr *)handle; + if (cntlr != NULL && cntlr->ops != NULL && cntlr->ops->rescanSdioDev != NULL) { + ret = cntlr->ops->rescanSdioDev(cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioOpen: sdio rescan fail!"); + MmcClose(handle); + return NULL; + } + } + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioOpen: get sdio dev fail!"); + MmcClose(handle); + return NULL; + } + ret = SdioDeviceFindFunction(sdio, config); + MmcDevicePut((struct MmcDevice *)sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioOpen: set function fail!"); + MmcClose(handle); + return NULL; + } + + return (DevHandle)cntlr; +} + +void SdioClose(DevHandle handle) +{ + (void)handle; +} + +int32_t SdioReadBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioReadBytes: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceIncrAddrReadBytes(sdio, data, addr, size); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioWriteBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioWriteBytes: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceIncrAddrWriteBytes(sdio, data, addr, size); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioReadBytesFromFixedAddr(DevHandle handle, uint8_t *data, + uint32_t addr, uint32_t size, uint32_t scatterLen) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioReadBytesFromFixedAddr: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceFixedAddrReadBytes(sdio, data, addr, size, scatterLen); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioWriteBytesToFixedAddr(DevHandle handle, uint8_t *data, + uint32_t addr, uint32_t size, uint32_t scatterLen) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioWriteBytesToFixedAddr: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceFixedAddrWriteBytes(sdio, data, addr, size, scatterLen); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioReadBytesFromFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioReadBytesFromFunc0: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceFunc0ReadBytes(sdio, data, addr, size); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioWriteBytesToFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioWriteBytesToFunc0: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceFunc0WriteBytes(sdio, data, addr, size); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioSetBlockSize(DevHandle handle, uint32_t blockSize) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioSetBlockSize: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceSetBlockSize(sdio, blockSize); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioGetCommonInfo(DevHandle handle, SdioCommonInfo *info, SdioCommonInfoType infoType) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioGetCommonInfo: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceGetCommonInfo(sdio, info, infoType); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioSetCommonInfo(DevHandle handle, SdioCommonInfo *info, SdioCommonInfoType infoType) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioSetCommonInfo: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceSetCommonInfo(sdio, info, infoType); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioFlushData(DevHandle handle) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioFlushData: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceFlushData(sdio); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +void SdioClaimHost(DevHandle handle) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioClaimHost: get sdio dev fail!"); + return; + } + ret = SdioDeviceClaimHost(sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioClaimHost: claim host fail!"); + } + MmcDevicePut((struct MmcDevice *)sdio); +} + +void SdioReleaseHost(DevHandle handle) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioReleaseHost: get sdio dev fail!"); + return; + } + ret = SdioDeviceReleaseHost(sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioReleaseHost: claim host fail!"); + } + MmcDevicePut((struct MmcDevice *)sdio); +} + +int32_t SdioEnableFunc(DevHandle handle) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioEnableFunc: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceEnableFunc(sdio); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioDisableFunc(DevHandle handle) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioDisableFunc: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceDisableFunc(sdio); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioClaimIrq(DevHandle handle, SdioIrqHandler *irqHandler) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioClaimIrq: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceClaimIrq(sdio, irqHandler); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} + +int32_t SdioReleaseIrq(DevHandle handle) +{ + int32_t ret; + struct SdioDevice *sdio = NULL; + + ret = SdioDeviceGetFromHandle(handle, &sdio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("SdioReleaseIrq: get sdio dev fail!"); + return ret; + } + ret = SdioDeviceReleaseIrq(sdio); + MmcDevicePut((struct MmcDevice *)sdio); + return ret; +} From fe10fdb01e5faa4cc46fdaf5bb90003c043a4424 Mon Sep 17 00:00:00 2001 From: lzl Date: Tue, 18 May 2021 03:41:21 +0000 Subject: [PATCH 08/21] new mmc code --- support/platform/include/mmc/mmc_protocol.h | 18 +++++++++--------- support/platform/src/common/platform_device.c | 1 - 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/support/platform/include/mmc/mmc_protocol.h b/support/platform/include/mmc/mmc_protocol.h index 96567b27..7bab66d5 100644 --- a/support/platform/include/mmc/mmc_protocol.h +++ b/support/platform/include/mmc/mmc_protocol.h @@ -328,15 +328,15 @@ enum MmcCsdSpecVersion { }; enum MmcCsdCardCmdClass { - MMC_CSD_CCC_BASIC = (1<<0), - MMC_CSD_CCC_BLOCK_READ = (1<<2), - MMC_CSD_CCC_BLOCK_WRITE = (1<<4), - MMC_CSD_CCC_ERASE = (1<<5), - MMC_CSD_CCC_WRITE_PROT = (1<<6), - MMC_CSD_CCC_LOCK_CARD = (1<<7), - MMC_CSD_CCC_APP_SPEC = (1<<8), - MMC_CSD_CCC_IO_MODE = (1<<9), - MMC_CSD_CCC_SWITCH = (1<<10), + MMC_CSD_CCC_BASIC = (1 << 0), + MMC_CSD_CCC_BLOCK_READ = (1 << 2), + MMC_CSD_CCC_BLOCK_WRITE = (1 << 4), + MMC_CSD_CCC_ERASE = (1 << 5), + MMC_CSD_CCC_WRITE_PROT = (1 << 6), + MMC_CSD_CCC_LOCK_CARD = (1 << 7), + MMC_CSD_CCC_APP_SPEC = (1 << 8), + MMC_CSD_CCC_IO_MODE = (1 << 9), + MMC_CSD_CCC_SWITCH = (1 << 10), }; enum MmcBusMode { diff --git a/support/platform/src/common/platform_device.c b/support/platform/src/common/platform_device.c index 91d5a0a9..0e70cddf 100644 --- a/support/platform/src/common/platform_device.c +++ b/support/platform/src/common/platform_device.c @@ -167,7 +167,6 @@ static void PlatformDeviceRemoveNotifier(struct PlatformDevice *device, struct P (void)OsalSpinUnlock(&device->spin); } - void PlatformDeviceUnregNotifier(struct PlatformDevice *device, struct PlatformNotifier *notifier) { if (device == NULL || notifier == NULL) { From d3d357cfcb046003886a107333f30c23dc251079 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 19 May 2021 09:29:19 +0800 Subject: [PATCH 09/21] =?UTF-8?q?IssueNo=EF=BC=9A#I3RW19=20Description:syn?= =?UTF-8?q?c=20L2=20peripheral=20code=20to=20L1=20Feature=20or=20Bugfix:Bu?= =?UTF-8?q?gfix=20Binary=20Source:=20NO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id70b0afae36d5e7b29aff158270d34c321f40d14 --- model/network/common/netdevice/net_device.c | 23 +++++++++--------- .../{compoments => components}/eapol/eapol.c | 4 ++-- .../{compoments => components}/eapol/eapol.h | 2 +- .../{compoments => components}/softap/ap.c | 3 +-- .../{compoments => components}/softap/ap.h | 0 .../core/{compoments => components}/sta/sta.c | 0 .../core/{compoments => components}/sta/sta.h | 0 model/network/wifi/core/hdf_wifi_core.c | 16 ++++++------- model/network/wifi/core/hdf_wifi_core.h | 4 ++-- model/network/wifi/include/hdf_wifi_cmd.h | 2 +- .../wifi/platform/include/hdf_wlan_services.h | 1 - .../platform/include/message/message_config.h | 4 ++-- .../platform/include/message/message_types.h | 4 ++-- .../wifi/platform/include/message/sidecar.h | 6 ++--- .../src/hdf_wlan_chipdriver_manager.c | 4 ++-- .../platform/src/hdf_wlan_config_parser.c | 24 +++++++++---------- .../platform/src/hdf_wlan_power_manager.c | 20 ++++++++-------- .../wifi/platform/src/hdf_wlan_product.c | 5 +++- .../platform/src/hdf_wlan_reset_manager.c | 8 +++---- .../wifi/platform/src/hdf_wlan_utils.c | 5 ++-- .../platform/src/message/message_dispatcher.c | 20 ++++++---------- .../platform/src/message/message_router.c | 23 +++++++++--------- .../platform/src/message/nodes/local_node.c | 11 ++++----- .../wifi/platform/src/message/sidecar.c | 4 ++-- .../driver/chipset/accel/accel_bmi160.c | 8 +++---- .../sensor/driver/common/src/sensor_common.c | 1 - .../driver/common/src/sensor_device_common.c | 3 +++ .../sensor/driver/common/src/sensor_parser.c | 18 +++++++------- .../driver/include/sensor_driver_type.h | 2 +- 29 files changed, 110 insertions(+), 115 deletions(-) rename model/network/wifi/core/{compoments => components}/eapol/eapol.c (98%) rename model/network/wifi/core/{compoments => components}/eapol/eapol.h (97%) rename model/network/wifi/core/{compoments => components}/softap/ap.c (99%) rename model/network/wifi/core/{compoments => components}/softap/ap.h (100%) rename model/network/wifi/core/{compoments => components}/sta/sta.c (100%) rename model/network/wifi/core/{compoments => components}/sta/sta.h (100%) diff --git a/model/network/common/netdevice/net_device.c b/model/network/common/netdevice/net_device.c index da504d16..2a336b30 100644 --- a/model/network/common/netdevice/net_device.c +++ b/model/network/common/netdevice/net_device.c @@ -17,12 +17,12 @@ static struct NetDeviceImpl *g_netDeviceImplTable[MAX_NETDEVICE_COUNT] = {NULL}; -static bool FindAvailableTable(int32_t *index) +static bool FindAvailableTable(uint32_t *index) { - int32_t i; + uint32_t i; if (index == NULL) { - HDF_LOGE("Find Available table index error!"); + HDF_LOGE("%s Find Available table index error!", __func__); return false; } for (i = 0; i < MAX_NETDEVICE_COUNT; i++) { @@ -34,7 +34,7 @@ static bool FindAvailableTable(int32_t *index) return false; } -static bool AddNetDeviceImplToTable(int32_t index, struct NetDeviceImpl *netDeviceImpl) +static bool AddNetDeviceImplToTable(uint32_t index, struct NetDeviceImpl *netDeviceImpl) { if (index >= MAX_NETDEVICE_COUNT) { HDF_LOGE("%s error because of not enough space!", __func__); @@ -68,7 +68,6 @@ static struct NetDeviceImpl *InitNetDeviceImpl(NetDevice *nd, NetIfCategory ifCa HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); return NULL; } - (void)memset_s(ndImpl, sizeof(struct NetDeviceImpl), 0, sizeof(struct NetDeviceImpl)); ndImpl->netDevice = nd; if (RegisterNetDeviceImpl(ndImpl) != HDF_SUCCESS) { @@ -100,6 +99,7 @@ static void DeInitNetDeviceImpl(struct NetDeviceImpl *netDeviceImpl) /* last release netDeviceImpl */ OsalMemFree(netDeviceImpl); + netDeviceImpl = NULL; HDF_LOGI("%s success!", __func__); return; } @@ -117,7 +117,7 @@ static struct NetDeviceImpl *GetImplByNetDevice(const struct NetDevice *netDevic } } } - HDF_LOGE("Don't Get Impl by netdevice"); + HDF_LOGE("%s Get Impl by netdevice failed", __func__); return ndImpl; } @@ -125,7 +125,7 @@ struct NetDevice *NetDeviceInit(const char *ifName, uint32_t len, NetIfCategory { NetDevice *netDevice = NULL; struct NetDeviceImpl *ndImpl = NULL; - int32_t index = 0; + uint32_t index = 0; int32_t ret; if ((ifName == NULL) || (strlen(ifName) != len) || (strlen(ifName) > IFNAMSIZ - 1)) { @@ -137,9 +137,8 @@ struct NetDevice *NetDeviceInit(const char *ifName, uint32_t len, NetIfCategory HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); return NULL; } - (void)memset_s(netDevice, sizeof(NetDevice), 0, sizeof(NetDevice)); - if (memcpy_s(netDevice->name, IFNAMSIZ, ifName, len + 1) != EOK) { - HDF_LOGE("%s fail: memcpy_s fail!", __func__); + if (strcpy_s(netDevice->name, IFNAMSIZ, ifName) != EOK) { + HDF_LOGE("%s fail: strcpy_s fail!", __func__); OsalMemFree(netDevice); return NULL; } @@ -318,7 +317,7 @@ static int32_t NetIfRxImpl(const struct NetDevice *netDevice, NetBuf *buff, Rece ProcessingResult ret = PROCESSING_CONTINUE; if (ndImpl == NULL || ndImpl->interFace == NULL || ndImpl->interFace->receive == NULL) { - HDF_LOGE("NetIfRxImpl fail : netdevice not exist!"); + HDF_LOGE("%s: NetIfRxImpl fail : netdevice not exist!", __func__); return HDF_ERR_INVALID_PARAM; } @@ -333,7 +332,7 @@ static int32_t NetIfRxImpl(const struct NetDevice *netDevice, NetBuf *buff, Rece HDF_LOGI("NetIfRxImpl specialEtherType Process not need TCP/IP stack!"); return HDF_SUCCESS; } else { - HDF_LOGE("NetIfRxImpl specialEtherType Process error"); + HDF_LOGE("%s: NetIfRxImpl specialEtherType Process error", __func__); return HDF_FAILURE; } } diff --git a/model/network/wifi/core/compoments/eapol/eapol.c b/model/network/wifi/core/components/eapol/eapol.c similarity index 98% rename from model/network/wifi/core/compoments/eapol/eapol.c rename to model/network/wifi/core/components/eapol/eapol.c index f1e02bbc..43811b22 100644 --- a/model/network/wifi/core/compoments/eapol/eapol.c +++ b/model/network/wifi/core/components/eapol/eapol.c @@ -75,7 +75,7 @@ static int32_t GetEapol(const struct NetDevice *netDevice, struct EapolRx *buff) p = NetBufGetAddress(netBuff, E_DATA_BUF); len = NetBufGetDataLen(netBuff); if (len > eapolRx->len) { - HDF_LOGE("%s fail : eapolRx->len too small! netBuff->len(%d) > eapolRx->len(%d).", + HDF_LOGE("%s fail : eapolRx->len too small! netBuff->len(%u) > eapolRx->len(%u).", __func__, netBuff->len, eapolRx->len); NetBufFree(netBuff); return HDF_FAILURE; @@ -158,7 +158,7 @@ static void HandleEapolQueue(struct EapolData *eapol) HDF_LOGE("%s discard pre netbuf : intervalTime(%lld) > EAPOL_MAX_ENQUEUE_TIME.", __func__, intervalTime); } else { - HDF_LOGE("%s discard pre netbuf : eapol->count(%d) = maxCount(%d).", __func__, eapol->count, maxCount); + HDF_LOGE("%s discard pre netbuf : eapol->count(%u) = maxCount(%u).", __func__, eapol->count, maxCount); } eapol->count--; eapol->enqueueTime = currentTime; diff --git a/model/network/wifi/core/compoments/eapol/eapol.h b/model/network/wifi/core/components/eapol/eapol.h similarity index 97% rename from model/network/wifi/core/compoments/eapol/eapol.h rename to model/network/wifi/core/components/eapol/eapol.h index d82b6c69..bebfdf9a 100644 --- a/model/network/wifi/core/compoments/eapol/eapol.h +++ b/model/network/wifi/core/components/eapol/eapol.h @@ -16,7 +16,7 @@ #define EAPOL_MAX_ENQUEUE_TIME 300 /* 300 Second */ struct EapolData { - bool regFlag; /* is already regstered */ + bool regFlag; /* is already registered */ uint16_t count; /* eapol frame count in NetBuffQueue. */ uint16_t maxCount; int64_t enqueueTime; /* record eapol frame time for dfx. */ diff --git a/model/network/wifi/core/compoments/softap/ap.c b/model/network/wifi/core/components/softap/ap.c similarity index 99% rename from model/network/wifi/core/compoments/softap/ap.c rename to model/network/wifi/core/components/softap/ap.c index 21daac1a..d685abed 100644 --- a/model/network/wifi/core/compoments/softap/ap.c +++ b/model/network/wifi/core/components/softap/ap.c @@ -72,7 +72,7 @@ static int32_t StartAp(struct NetDevice *netDev, WifiApSetting *apSettings) RETURN_IF_CHIPOPS_NOT_IMPLEMENT(chipDriver->apOps, ConfigAp); ret = chipDriver->apOps->ConfigAp(netDev, &apConf); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s:ConfigAp failed!ret=%d", ret); + HDF_LOGE("%s:ConfigAp failed!ret=%d", __func__, ret); return HDF_FAILURE; } @@ -378,7 +378,6 @@ static int32_t WifiCmdGetAssociatedStas(const RequestContext *context, struct Hd ret = GetAssociatedStas(netdev, num, rspData); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: fail to GetAssociatedStas,%d", __func__, ret); - return ret; } return ret; } diff --git a/model/network/wifi/core/compoments/softap/ap.h b/model/network/wifi/core/components/softap/ap.h similarity index 100% rename from model/network/wifi/core/compoments/softap/ap.h rename to model/network/wifi/core/components/softap/ap.h diff --git a/model/network/wifi/core/compoments/sta/sta.c b/model/network/wifi/core/components/sta/sta.c similarity index 100% rename from model/network/wifi/core/compoments/sta/sta.c rename to model/network/wifi/core/components/sta/sta.c diff --git a/model/network/wifi/core/compoments/sta/sta.h b/model/network/wifi/core/components/sta/sta.h similarity index 100% rename from model/network/wifi/core/compoments/sta/sta.h rename to model/network/wifi/core/components/sta/sta.h diff --git a/model/network/wifi/core/hdf_wifi_core.c b/model/network/wifi/core/hdf_wifi_core.c index 32179061..75c26ae9 100644 --- a/model/network/wifi/core/hdf_wifi_core.c +++ b/model/network/wifi/core/hdf_wifi_core.c @@ -39,13 +39,13 @@ int32_t HdfWifiGetBusIdx(void) * @brief as for now, we just support one wlan module in one board cause driver binds to wlan featere * due to that reason, once we detected one chip, we stop rescan. */ -int HdfWlanSdioScan(struct HdfWlanDevice *data, struct HdfConfigWlanBus *busConfig) +int32_t HdfWlanSdioScan(struct HdfWlanDevice *data, struct HdfConfigWlanBus *busConfig) { /* get config vendId, deviceId and chip-name which used in detect match process */ HdfWlanGetSdioTableByConfig(); HdfWlanSdioScanTriggerByBusIndex(busConfig->busIdx); - int ret = HdfWlanGetDetectedChip(data, busConfig); + int32_t ret = HdfWlanGetDetectedChip(data, busConfig); HdfWlanSdioDriverUnReg(); if (ret != HDF_SUCCESS) { return ret; @@ -54,7 +54,7 @@ int HdfWlanSdioScan(struct HdfWlanDevice *data, struct HdfConfigWlanBus *busConf return HDF_SUCCESS; } -static int HdfWifiDriverBind(struct HdfDeviceObject *dev) +static int32_t HdfWifiDriverBind(struct HdfDeviceObject *dev) { ErrorCode errCode; static struct IDeviceIoService wifiService = { @@ -179,7 +179,7 @@ static struct HdfChipDriverFactory *HdfWlanGetDriverFactory(const char *driverNa static int32_t HdfWlanDeinitInterface(struct HdfWlanDevice *device, const char *ifName, struct HdfChipDriverFactory *factory) { - int ret; + int32_t ret; struct NetDevice *netdev = NULL; struct HdfChipDriver *chipDriver = NULL; @@ -369,7 +369,7 @@ static struct HdfWlanDevice *ProbeDevice(struct HdfConfigWlanDevInst *deviceConf return device; } -int32_t DeinitDevice(struct HdfWlanDevice *device) +int32_t HdfWifiDeinitDevice(struct HdfWlanDevice *device) { struct HdfChipDriverFactory *chipDriverFact = NULL; int32_t ret; @@ -394,7 +394,7 @@ int32_t DeinitDevice(struct HdfWlanDevice *device) return HDF_SUCCESS; } -int32_t InitDevice(struct HdfWlanDevice *device) +int32_t HdfWifiInitDevice(struct HdfWlanDevice *device) { int32_t ret; struct HdfChipDriverFactory *chipDriverFact = NULL; @@ -424,7 +424,7 @@ int32_t InitDevice(struct HdfWlanDevice *device) /* thread callback function */ static int32_t HdfWlanInitThread(void *para) { - const uint32_t initDelaySec = 5; + const uint32_t initDelaySec = 15; struct HdfDeviceObject *device = (struct HdfDeviceObject *)para; struct SubscriberCallback callback = { NULL }; struct HdfConfigWlanDeviceList *devList = NULL; @@ -465,7 +465,7 @@ static int32_t HdfWlanInitThread(void *para) // Load chip driver (void)DevSvcManagerClntSubscribeService(wlanDevice->driverName, callback); - (void)InitDevice(wlanDevice); + (void)HdfWifiInitDevice(wlanDevice); } HDF_LOGV("%s:finished.", __func__); diff --git a/model/network/wifi/core/hdf_wifi_core.h b/model/network/wifi/core/hdf_wifi_core.h index c171fd61..78134dc5 100644 --- a/model/network/wifi/core/hdf_wifi_core.h +++ b/model/network/wifi/core/hdf_wifi_core.h @@ -17,9 +17,9 @@ extern "C" { #endif int32_t HdfWifiGetBusIdx(void); -int32_t DeinitDevice(struct HdfWlanDevice *device); +int32_t HdfWifiDeinitDevice(struct HdfWlanDevice *device); -int32_t InitDevice(struct HdfWlanDevice *device); +int32_t HdfWifiInitDevice(struct HdfWlanDevice *device); #ifdef __cplusplus } diff --git a/model/network/wifi/include/hdf_wifi_cmd.h b/model/network/wifi/include/hdf_wifi_cmd.h index aee3f941..9f0f17c0 100644 --- a/model/network/wifi/include/hdf_wifi_cmd.h +++ b/model/network/wifi/include/hdf_wifi_cmd.h @@ -278,7 +278,7 @@ typedef struct { typedef struct { void *callback; - void *contex; + void *context; } WifiEnableEapol; typedef struct { diff --git a/model/network/wifi/platform/include/hdf_wlan_services.h b/model/network/wifi/platform/include/hdf_wlan_services.h index e419062d..cbc7e5fb 100644 --- a/model/network/wifi/platform/include/hdf_wlan_services.h +++ b/model/network/wifi/platform/include/hdf_wlan_services.h @@ -29,7 +29,6 @@ enum BaseCommands { CMD_BASE_GET_ADDR, CMD_BASE_SET_MODE, CMD_BASE_GET_HW_FEATURE = 10, -// CMD_BASE_SCAN, CMD_BASE_SET_NETDEV, CMD_BASE_SEND_ACTION, CMD_BASE_SET_CLIENT, diff --git a/model/network/wifi/platform/include/message/message_config.h b/model/network/wifi/platform/include/message/message_config.h index 1a301bcb..cc2d47ea 100644 --- a/model/network/wifi/platform/include/message/message_config.h +++ b/model/network/wifi/platform/include/message/message_config.h @@ -6,8 +6,8 @@ * See the LICENSE file in the root of this repository for complete details. */ -#ifndef __MESSAGE_CONFIG_H__ -#define __MESSAGE_CONFIG_H__ +#ifndef MESSAGE_CONFIG_H +#define MESSAGE_CONFIG_H #include "message_types.h" #ifndef MESSAGE_ENGINE_MAX_SERVICE diff --git a/model/network/wifi/platform/include/message/message_types.h b/model/network/wifi/platform/include/message/message_types.h index 32dce6f5..b973d4c6 100644 --- a/model/network/wifi/platform/include/message/message_types.h +++ b/model/network/wifi/platform/include/message/message_types.h @@ -6,8 +6,8 @@ * See the LICENSE file in the root of this repository for complete details. */ -#ifndef __MESSAGE_TYPES_H__ -#define __MESSAGE_TYPES_H__ +#ifndef MESSAGE_TYPES_H +#define MESSAGE_TYPES_H #include "hdf_base.h" typedef uint8_t NodeId; diff --git a/model/network/wifi/platform/include/message/sidecar.h b/model/network/wifi/platform/include/message/sidecar.h index 4e1d7f59..10155c11 100644 --- a/model/network/wifi/platform/include/message/sidecar.h +++ b/model/network/wifi/platform/include/message/sidecar.h @@ -6,8 +6,8 @@ * See the LICENSE file in the root of this repository for complete details. */ -#ifndef __SIDECAR_H__ -#define __SIDECAR_H__ +#ifndef SIDECAR_H +#define SIDECAR_H #include "hdf_base.h" #include "hdf_device_desc.h" #include "osal/osal_sem.h" @@ -29,7 +29,7 @@ enum MessageType { uint8_t senderId; \ uint8_t receiverId; \ uint8_t requestType; \ - bool corssNode; \ + bool crossNode; \ struct HdfDeviceIoClient *client #define RESERVED_SERVICE_ID 0 diff --git a/model/network/wifi/platform/src/hdf_wlan_chipdriver_manager.c b/model/network/wifi/platform/src/hdf_wlan_chipdriver_manager.c index 63a47e9c..85580e6b 100644 --- a/model/network/wifi/platform/src/hdf_wlan_chipdriver_manager.c +++ b/model/network/wifi/platform/src/hdf_wlan_chipdriver_manager.c @@ -46,13 +46,13 @@ int32_t HdfWlanRegChipDriver(struct HdfChipDriverFactory *obj) return HDF_ERR_INVALID_PARAM; } if (HdfWlanGetChipDriverByName(obj->driverName) != NULL) { - HDF_LOGW("%s: chipdriver factory is already registed.name=%s", __func__, obj->driverName); + HDF_LOGW("%s: chipdriver factory is already registered.name=%s", __func__, obj->driverName); return HDF_SUCCESS; } for (index = 0; index < MAX_CHIPDRIVER_COUNT; index++) { if (g_wlanChipDriverManagerFactory[index] == NULL) { g_wlanChipDriverManagerFactory[index] = obj; - HDF_LOGI("%s:Chip driver %s registed.", __func__, obj->driverName); + HDF_LOGI("%s:Chip driver %s registered.", __func__, obj->driverName); return HDF_SUCCESS; } } diff --git a/model/network/wifi/platform/src/hdf_wlan_config_parser.c b/model/network/wifi/platform/src/hdf_wlan_config_parser.c index b55b3935..d32facbb 100644 --- a/model/network/wifi/platform/src/hdf_wlan_config_parser.c +++ b/model/network/wifi/platform/src/hdf_wlan_config_parser.c @@ -35,7 +35,7 @@ static int32_t ParseWlanStaConfig(const struct DeviceResourceNode *node, struct HDF_LOGE("%s: GetUint8 fail!", __func__); return HDF_FAILURE; } - HDF_LOGD("%s: name=%s, mode=%d!", __func__, staConfig->name, staConfig->mode); + HDF_LOGD("%s: name=%s, mode=%u!", __func__, staConfig->name, staConfig->mode); return HDF_SUCCESS; } @@ -73,7 +73,7 @@ static int32_t ParseWlanApConfig(const struct DeviceResourceNode *node, struct H HDF_LOGE("%s: get userResNum fail!", __func__); return HDF_FAILURE; } - HDF_LOGD("%s: name=%s, mode=%d, vapResNum=%d, userResNum=%d!", __func__, apConfig->name, apConfig->mode, + HDF_LOGD("%s: name=%s, mode=%u, vapResNum=%u, userResNum=%u!", __func__, apConfig->name, apConfig->mode, apConfig->vapResNum, apConfig->userResNum); return HDF_SUCCESS; } @@ -102,7 +102,7 @@ static int32_t ParseWlanP2PConfig(const struct DeviceResourceNode *node, struct HDF_LOGE("%s: mode fail!", __func__); return HDF_FAILURE; } - HDF_LOGD("%s: name=%s, mode=%d", __func__, p2pConfig->name, p2pConfig->mode); + HDF_LOGD("%s: name=%s, mode=%u", __func__, p2pConfig->name, p2pConfig->mode); return HDF_SUCCESS; } @@ -125,7 +125,7 @@ static int32_t ParseWlanMac80211Config(const struct DeviceResourceNode *node, st HDF_LOGE("%s: mode fail!", __func__); return HDF_FAILURE; } - HDF_LOGD("%s: mode=%d", __func__, macConfig->mode); + HDF_LOGD("%s: mode=%u", __func__, macConfig->mode); return HDF_SUCCESS; } @@ -211,10 +211,11 @@ static int32_t ParseWlanModuleConfig(const struct DeviceResourceNode *node, stru return HDF_SUCCESS; } /* BEGIN for WLAN2.1 : Added by hdf-wlan */ -static int32_t ParseWlanPowerConfig(const struct DeviceResourceNode *node, struct HdfConfigWlanPower *masterPowerConfig) +static int32_t ParseWlanPowerConfig(const struct DeviceResourceNode *node, + struct HdfConfigWlanPower *primaryPowerConfig) { struct DeviceResourceIface *drsOps = NULL; - if (node == NULL || masterPowerConfig == NULL) { + if (node == NULL || primaryPowerConfig == NULL) { HDF_LOGE("%s: one of the input para is NULL!", __func__); return HDF_FAILURE; } @@ -224,21 +225,21 @@ static int32_t ParseWlanPowerConfig(const struct DeviceResourceNode *node, struc return HDF_FAILURE; } - if (drsOps->GetUint8(node, "powerSeqDelay", &masterPowerConfig->powerSeqDelay, 0) != HDF_SUCCESS) { + if (drsOps->GetUint8(node, "powerSeqDelay", &primaryPowerConfig->powerSeqDelay, 0) != HDF_SUCCESS) { HDF_LOGE("%s: powersSeqDelay fail!", __func__); return HDF_FAILURE; } - if (drsOps->GetUint8(node, "powerType", &masterPowerConfig->powerType, 0) != HDF_SUCCESS) { + if (drsOps->GetUint8(node, "powerType", &primaryPowerConfig->powerType, 0) != HDF_SUCCESS) { HDF_LOGE("%s: powerType fail!", __func__); return HDF_FAILURE; } - if (drsOps->GetUint8(node, "gpioId", &masterPowerConfig->gpioId, 0) != HDF_SUCCESS) { + if (drsOps->GetUint8(node, "gpioId", &primaryPowerConfig->gpioId, 0) != HDF_SUCCESS) { HDF_LOGE("%s: gpioId fail!", __func__); return HDF_FAILURE; } - if (drsOps->GetUint8(node, "activeLevel", &masterPowerConfig->activeLevel, 0) != HDF_SUCCESS) { + if (drsOps->GetUint8(node, "activeLevel", &primaryPowerConfig->activeLevel, 0) != HDF_SUCCESS) { HDF_LOGE("%s: activeLevel fail!", __func__); return HDF_FAILURE; } @@ -269,7 +270,7 @@ static int32_t ParseWlanPowersConfig(const struct DeviceResourceNode *node, stru } const struct DeviceResourceNode *secPowerNode = drsOps->GetChildNode(node, "power1"); - if (fstPowerNode == NULL) { + if (secPowerNode == NULL) { HDF_LOGE("%s: get power1 config fail!", __func__); return HDF_FAILURE; } @@ -451,7 +452,6 @@ static int32_t ParseWlanChipSdioConfig(const struct DeviceResourceNode *node, st HDF_LOGE("%s: deviceId fail!", __func__); return HDF_FAILURE; } - HDF_LOGI("%s: SDIO vendor=%u, device=%u", __func__, sdioArgs->vendorId, sdioArgs->deviceId[0]); return HDF_SUCCESS; } diff --git a/model/network/wifi/platform/src/hdf_wlan_power_manager.c b/model/network/wifi/platform/src/hdf_wlan_power_manager.c index 09494aba..50592e73 100644 --- a/model/network/wifi/platform/src/hdf_wlan_power_manager.c +++ b/model/network/wifi/platform/src/hdf_wlan_power_manager.c @@ -16,13 +16,13 @@ /* power manager begin */ enum PowerType { - PowerNotManaged = 0, - PowerManagedByGPIO = 1 + POWER_NOT_MANAGED = 0, + POWER_MANAGED_BY_GPIO = 1 }; enum GPIOActiveLevel { - ActiveLow = 0, - ActiveHigh + ACTIVE_LOW = 0, + ACTIVE_HIGH }; /* powerCount=1 single power source */ @@ -44,7 +44,7 @@ static int32_t HdfWlanSinglePowerActive(struct HdfConfigWlanPower* powerDate) HDF_LOGE("%s:powerDate is NULL", __func__); return HDF_FAILURE; } - if (powerDate->powerType != PowerNotManaged) { + if (powerDate->powerType != POWER_NOT_MANAGED) { HDF_LOGI("%s:power type is always on", __func__); return HDF_SUCCESS; } @@ -64,14 +64,14 @@ static int32_t HdfWlanSinglePowerActive(struct HdfConfigWlanPower* powerDate) static int32_t HdfWlanSingleDeActive(struct HdfConfigWlanPower* powerDate) { int32_t ret; - uint8_t deActicve; + uint8_t deActive; if (powerDate == NULL) { HDF_LOGE("%s: powerDate is NULL", __func__); return HDF_FAILURE; } - deActicve = !powerDate->activeLevel; - if (powerDate->powerType == PowerNotManaged) { + deActive = !powerDate->activeLevel; + if (powerDate->powerType == POWER_NOT_MANAGED) { HDF_LOGE("%s:power type is not supported in current version", __func__); return HDF_FAILURE; } @@ -80,7 +80,7 @@ static int32_t HdfWlanSingleDeActive(struct HdfConfigWlanPower* powerDate) HDF_LOGE("%s:set dir fail! ret:%d\n", __func__, ret); return ret; } - ret = GpioWrite(powerDate->gpioId, deActicve); + ret = GpioWrite(powerDate->gpioId, deActive); return HDF_SUCCESS; } @@ -138,7 +138,7 @@ int32_t HdfWlanPowerMgrRelease(struct PowerManager* powerMgr) return HDF_SUCCESS; } /** - * @brief create powers manager accoding to the powers config + * @brief create powers manager according to the powers config */ struct PowerManager* HdfWlanCreatePowerManager(const struct HdfConfWlanPowers *configPowers) { diff --git a/model/network/wifi/platform/src/hdf_wlan_product.c b/model/network/wifi/platform/src/hdf_wlan_product.c index 6c75f2ba..3a50385d 100644 --- a/model/network/wifi/platform/src/hdf_wlan_product.c +++ b/model/network/wifi/platform/src/hdf_wlan_product.c @@ -90,12 +90,15 @@ struct WifiModule *HdfWlanGetModule(void) struct HdfDeviceObject *HdfWlanGetDevice(void) { + if (g_hdfWlanProductData == NULL) { + return NULL; + } return g_hdfWlanProductData->device; } struct HdfWlanDevice *HdfWlanGetWlanDevice(uint8_t chipId) { - if (chipId >= MAX_WLAN_DEVICE) { + if (chipId >= MAX_WLAN_DEVICE || g_hdfWlanProductData == NULL) { return NULL; } return g_hdfWlanProductData->wlanDevice[chipId]; diff --git a/model/network/wifi/platform/src/hdf_wlan_reset_manager.c b/model/network/wifi/platform/src/hdf_wlan_reset_manager.c index 188950b8..595db575 100644 --- a/model/network/wifi/platform/src/hdf_wlan_reset_manager.c +++ b/model/network/wifi/platform/src/hdf_wlan_reset_manager.c @@ -18,8 +18,8 @@ * @brief constant reset manage type */ enum ResetType { - ResetAlwaysOn = 0, - ResetManagedByGPIO = 1 + RESET_ALWAYS_ON = 0, + RESET_MANAGED_BY_GPIO = 1 }; struct HdfWlanResetData { @@ -44,7 +44,7 @@ int32_t HdfChipReset(struct ResetManager *resetManager) return HDF_FAILURE; } resetMgrImpl = (struct ResetManagerImpl*)resetManager; - if (resetMgrImpl->resetData.resetCfg.resetType == ResetAlwaysOn) { + if (resetMgrImpl->resetData.resetCfg.resetType == RESET_ALWAYS_ON) { HDF_LOGE("%s: the reset type is not managed", __func__); return HDF_FAILURE; } @@ -62,7 +62,7 @@ int32_t HdfChipReset(struct ResetManager *resetManager) ret = GpioWrite(resetMgrImpl->resetData.resetCfg.gpioId, !resetMgrImpl->resetData.resetCfg.activeLevel); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: write deactive fail! ret=%d", __func__, ret); + HDF_LOGE("%s: write deactivate fail! ret=%d", __func__, ret); return ret; } OsalMSleep(resetMgrImpl->resetData.bootUpHoldTime); diff --git a/model/network/wifi/platform/src/hdf_wlan_utils.c b/model/network/wifi/platform/src/hdf_wlan_utils.c index 8309ceb8..cc92c61e 100644 --- a/model/network/wifi/platform/src/hdf_wlan_utils.c +++ b/model/network/wifi/platform/src/hdf_wlan_utils.c @@ -72,7 +72,7 @@ int32_t RenewNetDevice(NetDevice **netDev) NetDevice *result = NULL; struct HdfWifiNetDeviceData *data = NULL; int32_t ret; - if (netDev == NULL) { + if (netDev == NULL || *netDev == NULL) { HDF_LOGE("%s:NULL ptr!", __func__); return HDF_FAILURE; } @@ -160,7 +160,6 @@ struct NetDevice *AllocPlatformNetDevice(struct HdfWlanDevice *device) ret = GetPlatformIfName(id, ifName, IFNAMSIZ); if (ret != HDF_SUCCESS) { - OsalMemFree(data); break; } #ifdef _PRE_HDF_LINUX @@ -254,7 +253,7 @@ char *HdfWlanGetIfNames(const uint8_t chipId, uint8_t *ifNameCount) return NULL; } - if (ifNameCount == 0) { + if (*ifNameCount == 0) { return ifNames; } diff --git a/model/network/wifi/platform/src/message/message_dispatcher.c b/model/network/wifi/platform/src/message/message_dispatcher.c index 97d5747a..23056b80 100644 --- a/model/network/wifi/platform/src/message/message_dispatcher.c +++ b/model/network/wifi/platform/src/message/message_dispatcher.c @@ -36,7 +36,7 @@ void ReleaseMessageContext(MessageContext *context) context->rspData = NULL; } - if (context->corssNode || + if (context->crossNode || (context->requestType != MESSAGE_TYPE_SYNC_REQ && context->requestType != MESSAGE_TYPE_SYNC_RSP)) { // Sync request message may use stack mem.Memory is managed by user if (context->reqData != NULL) { @@ -104,7 +104,7 @@ ErrorCode AppendToLocalDispatcher(MessageDispatcher *dispatcher, const uint8_t p void SetToResponse(MessageContext *context) { if (context->requestType != MESSAGE_TYPE_ASYNC_REQ && context->requestType != MESSAGE_TYPE_SYNC_REQ) { - HDF_LOGE("Only sync and async message can send response!type=%d", context->requestType); + HDF_LOGE("Only sync and async message can send response!type=%u", context->requestType); return; } ServiceId senderId = context->senderId; @@ -124,7 +124,6 @@ static void HandleAsyncResponse(MessageContext *context) } ReleaseMessageContext(context); - context = NULL; } static void HandleSyncResponse(MessageContext *context) @@ -135,7 +134,7 @@ static void HandleSyncResponse(MessageContext *context) } HDF_STATUS status = OsalSemPost(&context->rspSemaphore); if (status != HDF_SUCCESS) { - HDF_LOGE("Send semaphore failed!CMD=%d,Sender=%d,Receiver=%d", context->commandId, context->senderId, + HDF_LOGE("Send semaphore failed!CMD=%u,Sender=%u,Receiver=%u", context->commandId, context->senderId, context->receiverId); } return; @@ -148,13 +147,13 @@ static void HandleRequestMessage(MessageContext *context) RemoteService *rspService = NULL; do { if (targetService == NULL) { - HDF_LOGE("%s:Service %d is not available!", __func__, context->receiverId); + HDF_LOGE("%s:Service %u is not available!", __func__, context->receiverId); errCode = ME_ERROR_NULL_PTR; break; } if (targetService->ExecRequestMsg == NULL) { - HDF_LOGE("%s:Service %d has no ExecMsg method!", __func__, context->receiverId); + HDF_LOGE("%s:Service %u has no ExecMsg method!", __func__, context->receiverId); errCode = ME_ERROR_NULL_PTR; break; } @@ -214,7 +213,7 @@ static void HandleMessage(MessageContext *context) HandleAsyncResponse(context); break; default: - HDF_LOGE("Unsupported message type %d", context->requestType); + HDF_LOGE("Unsupported message type %u", context->requestType); } } } @@ -323,12 +322,7 @@ static ErrorCode StartDispatcher(MessageDispatcher *dispatcher) do { OsalMSleep(1); } while (dispatcher->status == ME_STATUS_STARTTING); - - if (dispatcher->status == ME_STATUS_RUNNING) { - return ME_SUCCESS; - } else { - return ME_ERROR_WRONG_STATUS; - } + return (dispatcher->status == ME_STATUS_RUNNING) ? ME_SUCCESS : ME_ERROR_WRONG_STATUS; } static void ShutdownDispatcher(MessageDispatcher *dispatcher) diff --git a/model/network/wifi/platform/src/message/message_router.c b/model/network/wifi/platform/src/message/message_router.c index ab77a65d..3776a3e6 100644 --- a/model/network/wifi/platform/src/message/message_router.c +++ b/model/network/wifi/platform/src/message/message_router.c @@ -6,6 +6,7 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "message_router.h" #include "hdf_base.h" #ifdef USERSPACE_CLIENT_SUPPORT #include @@ -14,7 +15,6 @@ #include "utils/hdf_log.h" #include "osal/osal_mutex.h" #include "securec.h" -#include "message_router.h" #include "message_router_inner.h" #include "message_dispatcher.h" @@ -25,7 +25,7 @@ #endif #ifndef UINT8_MAX -#define UINT8_MAX 256 +#define UINT8_MAX 255 #endif #if MESSAGE_ENGINE_MAX_DISPATCHER > UINT8_MAX @@ -71,7 +71,7 @@ static void ReleaseRemoteService(RemoteService *service) static MessageDispatcher *RefDispatcherInner(const DispatcherId dispatcherId, bool requireLock) { if (dispatcherId >= MESSAGE_ENGINE_MAX_DISPATCHER) { - HDF_LOGE("%s:Input ID is too big.input=%d", __func__, dispatcherId); + HDF_LOGE("%s:Input ID is too big.input=%u", __func__, dispatcherId); return NULL; } @@ -106,7 +106,7 @@ static MessageDispatcher *RefDispatcherInner(const DispatcherId dispatcherId, bo static ErrorCode RegDispatcher(DispatcherId dispatcherId, MessageDispatcher *dispatcher) { if (dispatcherId >= MESSAGE_ENGINE_MAX_DISPATCHER) { - HDF_LOGE("%s:dispatcher id is too big!id=%d", __func__, dispatcherId); + HDF_LOGE("%s:dispatcher id is too big!id=%u", __func__, dispatcherId); return ME_ERROR_PARA_WRONG; } @@ -122,7 +122,7 @@ static ErrorCode RegDispatcher(DispatcherId dispatcherId, MessageDispatcher *dis break; } if (g_dispatchers[dispatcherId] != NULL) { - HDF_LOGE("%s:DispatcherId conflict!ID=%d", __func__, dispatcherId); + HDF_LOGE("%s:DispatcherId conflict!ID=%u", __func__, dispatcherId); errCode = ME_ERROR_DISPATCHERID_CONFLICT; } else { g_dispatchers[dispatcherId] = dispatcher; @@ -154,7 +154,7 @@ ErrorCode AddDispatcher(DispatcherConfig *config) if (dispatcher->Start != NULL) { errCode = dispatcher->Start(dispatcher); if (errCode != ME_SUCCESS) { - HDF_LOGE("%s:Start dispatcher %d failed!errCode=%d", __func__, config->dispatcherId, errCode); + HDF_LOGE("%s:Start dispatcher %u failed!errCode=%d", __func__, config->dispatcherId, errCode); break; } } @@ -242,7 +242,7 @@ static ErrorCode DoRegistService(const NodeId nodeId, const DispatcherId dispatc return ME_ERROR_WRONG_STATUS; } - HDF_LOGW("%s:Regist service Node:%d;Dispatcher:%d;Service:%d", __func__, nodeId, dispatcherId, + HDF_LOGW("%s:Register service Node:%d;Dispatcher:%u;Service:%u", __func__, nodeId, dispatcherId, remoteService->serviceId); if (g_servicesIndex[remoteService->serviceId].remoteService != NULL) { @@ -263,7 +263,7 @@ static ErrorCode RegistServiceInner(const NodeId nodeId, const DispatcherId disp } if (mapper->serviceId >= MESSAGE_ENGINE_MAX_SERVICE) { - HDF_LOGE("%s:serviceId exceed max value! ServiceId=%d", __func__, mapper->serviceId); + HDF_LOGE("%s:serviceId exceed max value! ServiceId=%u", __func__, mapper->serviceId); return ME_ERROR_PARA_WRONG; } HDF_STATUS status = OsalMutexTimedLock(&g_routerMutex, HDF_WAIT_FOREVER); @@ -275,6 +275,7 @@ static ErrorCode RegistServiceInner(const NodeId nodeId, const DispatcherId disp MessageNode *node = RefMessageNode(nodeId, false); if (node == NULL) { HDF_LOGE("%s:Node not found!", __func__); + OsalMutexUnlock(&g_routerMutex); return ME_ERROR_NO_SUCH_NODE; } RemoteService *remoteService = NULL; @@ -556,7 +557,7 @@ static ErrorCode DoStartMessageRouter(uint8_t nodesConfig) return ME_ERROR_MUTI_INIT_NOT_ALLOWED; } - for (i = 0; i < UINT8_MAX && i < MESSAGE_ENGINE_MAX_SERVICE; i++) { + for (i = 0; i < MESSAGE_ENGINE_MAX_SERVICE; i++) { g_servicesIndex[i].remoteService = NULL; g_servicesIndex[i].nodeIndex = NO_SUCH_NODE_INDEX; g_servicesIndex[i].dispatcherId = BAD_DISPATCHER_ID; @@ -599,10 +600,10 @@ ErrorCode EnableDefaultDispatcher(void) .queueSize = DEFAULT_DISPATCHER_QUEUE_SIZE, .priorityLevelCount = DEFAULT_DISPATCHER_PRIORITY_COUNT }; - HDF_LOGI("Regist default dispatcher..."); + HDF_LOGI("Register default dispatcher..."); ErrorCode errCode = AddDispatcher(&config); if (errCode != ME_SUCCESS) { - HDF_LOGE("Regist default dispatcher failed!ret=%d", errCode); + HDF_LOGE("Register default dispatcher failed!ret=%d", errCode); } return errCode; } diff --git a/model/network/wifi/platform/src/message/nodes/local_node.c b/model/network/wifi/platform/src/message/nodes/local_node.c index 5ac55373..b5b8c89a 100644 --- a/model/network/wifi/platform/src/message/nodes/local_node.c +++ b/model/network/wifi/platform/src/message/nodes/local_node.c @@ -67,18 +67,19 @@ static void HandleResponseMessage(const RemoteService *service, MessageContext * } ReleaseMessageContext(context); } else { - HDF_LOGE("%s:Response type not supported!type=%d", __func__, context->requestType); + HDF_LOGE("%s:Response type not supported!type=%u", __func__, context->requestType); } } ErrorCode SendMessageLocalNode(const RemoteService *service, MessageContext *context) { + uint8_t pri = HIGHEST_PRIORITY; if (service == NULL || context == NULL) { HDF_LOGE("%s:Input is NULL!", __func__); return ME_ERROR_NULL_PTR; } - if (!context->corssNode && context->requestType == MESSAGE_TYPE_SYNC_REQ) { + if (!context->crossNode && context->requestType == MESSAGE_TYPE_SYNC_REQ) { HandleRequestMessage(service, context); SetToResponse(context); return context->responseStatus; @@ -103,11 +104,9 @@ ErrorCode SendMessageLocalNode(const RemoteService *service, MessageContext *con return ME_ERROR_NO_SUCH_COMMAND; } - uint8_t pri = localService->mapper->messages[context->commandId].pri; - return localService->dispatcher->AppendMessage(localService->dispatcher, pri, context); - } else { - return localService->dispatcher->AppendMessage(localService->dispatcher, HIGHEST_PRIORITY, context); + pri = localService->mapper->messages[context->commandId].pri; } + return localService->dispatcher->AppendMessage(localService->dispatcher, pri, context); } } diff --git a/model/network/wifi/platform/src/message/sidecar.c b/model/network/wifi/platform/src/message/sidecar.c index b49e9abd..dc8692e9 100644 --- a/model/network/wifi/platform/src/message/sidecar.c +++ b/model/network/wifi/platform/src/message/sidecar.c @@ -50,7 +50,7 @@ static MessageContext *CreateMessageContext(ServiceId sender, ServiceId receiver context->senderId = sender; context->receiverId = receiver; context->reqData = sendData; - context->corssNode = false; + context->crossNode = false; return context; } @@ -260,7 +260,7 @@ Service *InitService(struct ServiceDef *def, const ServiceCfg *cfg) service->privateData = NULL; OsalMemFree(service); service = NULL; - HDF_LOGE("Regist service failed!serviceId=%d,ret=%d", def->serviceId, errCode); + HDF_LOGE("Register service failed!serviceId=%d,ret=%d", def->serviceId, errCode); return NULL; } return service; diff --git a/model/sensor/driver/chipset/accel/accel_bmi160.c b/model/sensor/driver/chipset/accel/accel_bmi160.c index f82c0129..382c60f9 100644 --- a/model/sensor/driver/chipset/accel/accel_bmi160.c +++ b/model/sensor/driver/chipset/accel/accel_bmi160.c @@ -25,12 +25,12 @@ static int32_t ReadBmi160RawData(struct SensorCfgData *data, struct AccelData *r OsalTimespec time; (void)memset_s(&time, sizeof(time), 0, sizeof(time)); - (void)memset_s(®, sizeof(reg), 0, sizeof(reg)); - + (void)memset_s(reg, sizeof(reg), 0, sizeof(reg)); CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); + if (OsalGetTime(&time) != HDF_SUCCESS) { - HDF_LOGE("%s: Get accel system time failed", __func__); + HDF_LOGE("%s: Get time failed", __func__); return HDF_FAILURE; } *timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT; /* unit nanosecond */ @@ -120,7 +120,7 @@ static int32_t InitAccelPreConfig(void) return HDF_FAILURE; } if (SetSensorPinMux(SENSOR_I2C6_CLK_REG_ADDR, SENSOR_ADDR_WIDTH_4_BYTE, SENSOR_I2C_REG_CFG) != HDF_SUCCESS) { - HDF_LOGE("%s: ClK write mux pin failed", __func__); + HDF_LOGE("%s: Clk write mux pin failed", __func__); return HDF_FAILURE; } diff --git a/model/sensor/driver/common/src/sensor_common.c b/model/sensor/driver/common/src/sensor_common.c index 411bf25c..a48719f9 100644 --- a/model/sensor/driver/common/src/sensor_common.c +++ b/model/sensor/driver/common/src/sensor_common.c @@ -36,7 +36,6 @@ int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, if (busCfg->busType == SENSOR_BUS_I2C) { CHECK_NULL_PTR_RETURN_VALUE(busCfg->i2cCfg.handle, HDF_FAILURE); - (void)memset_s(msg, sizeof(msg), 0, sizeof(msg)); msg[I2C_READ_MSG_ADDR_IDX].addr = busCfg->i2cCfg.devAddr; msg[I2C_READ_MSG_ADDR_IDX].flags = 0; diff --git a/model/sensor/driver/common/src/sensor_device_common.c b/model/sensor/driver/common/src/sensor_device_common.c index da1e2e85..08fc9f4e 100644 --- a/model/sensor/driver/common/src/sensor_device_common.c +++ b/model/sensor/driver/common/src/sensor_device_common.c @@ -83,6 +83,8 @@ static int32_t SensorOpsReadCheck(struct SensorBusCfg *busCfg, struct SensorRegC uint16_t busMask = 0xffff; int32_t ret; + CHECK_NULL_PTR_RETURN_VALUE(busCfg, HDF_FAILURE); + if (busCfg->busType == SENSOR_BUS_I2C) { ret = ReadSensor(busCfg, cfgItem->regAddr, (uint8_t *)&value, sizeof(value)); CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read i2c reg"); @@ -123,6 +125,7 @@ int32_t SetSensorRegCfgArray(struct SensorBusCfg *busCfg, const struct SensorReg CHECK_NULL_PTR_RETURN_VALUE(group->regCfgItem, HDF_FAILURE); count = sizeof(g_doOpsCall) / sizeof(g_doOpsCall[0]); + while (num < group->itemNum) { cfgItem = (group->regCfgItem + num); if (cfgItem->opsType >= count) { diff --git a/model/sensor/driver/common/src/sensor_parser.c b/model/sensor/driver/common/src/sensor_parser.c index 96392aca..0030fc48 100644 --- a/model/sensor/driver/common/src/sensor_parser.c +++ b/model/sensor/driver/common/src/sensor_parser.c @@ -22,22 +22,18 @@ static char *g_sensorRegGroupName[SENSOR_GROUP_MAX] = { static uint32_t GetSensorRegGroupNameIndex(const char *name) { - uint32_t index = 0xFF; + uint32_t index; if (name == NULL) { - return index; + return SENSOR_GROUP_MAX; } for (index = 0; index < SENSOR_GROUP_MAX; ++index) { - if (strcmp(name, g_sensorRegGroupName[index]) == 0) { + if ((g_sensorRegGroupName[index] != NULL) && (strcmp(name, g_sensorRegGroupName[index]) == 0)) { break; } } - if (index == SENSOR_GROUP_MAX) { - index = 0xFF; - } - return index; } @@ -73,6 +69,11 @@ static int32_t ParseSensorRegItem(struct DeviceResourceIface *parser, const stru CHECK_NULL_PTR_RETURN_VALUE(groupName, HDF_ERR_INVALID_PARAM); int32_t num = parser->GetElemNum(regNode, groupName); + if (num <= 0 || num > SENSOR_CONFIG_MAX_ITEM) { + HDF_LOGE("%s: parser %s element num failed", __func__, groupName); + return HDF_SUCCESS; + } + uint16_t *buf = (uint16_t *)OsalMemCalloc(sizeof(uint16_t) * num); CHECK_NULL_PTR_RETURN_VALUE(buf, HDF_ERR_MALLOC_FAIL); @@ -196,7 +197,6 @@ int32_t GetSensorBusHandle(struct SensorBusCfg *busCfg) if (busCfg->busType == SENSOR_BUS_I2C) { int16_t busNum = busCfg->i2cCfg.busNum; busCfg->i2cCfg.handle = I2cOpen(busNum); - if (busCfg->i2cCfg.handle == NULL) { HDF_LOGE("%s: sensor i2c Handle invalid", __func__); return HDF_FAILURE; @@ -246,7 +246,7 @@ int32_t DetectSensorDevice(struct SensorCfgData *config) } if (value != chipIdValue) { - HDF_LOGE("%s: sensor chip[0x%x] id [0x%x] detect value[%d]", __func__, chipIdReg, chipIdValue, value); + HDF_LOGE("%s: sensor chip[0x%x] id [0x%x] detect value[%u]", __func__, chipIdReg, chipIdValue, value); (void)ReleaseSensorBusHandle(&config->busCfg); return HDF_FAILURE; } diff --git a/model/sensor/driver/include/sensor_driver_type.h b/model/sensor/driver/include/sensor_driver_type.h index ef2d3c70..dfbe3c39 100644 --- a/model/sensor/driver/include/sensor_driver_type.h +++ b/model/sensor/driver/include/sensor_driver_type.h @@ -37,7 +37,7 @@ enum SensorWorkMode { }; enum SensorTag { - SENSOR_TAG_NONE = 0, /**< No sensor type for sensor test*/ + SENSOR_TAG_NONE = 0, /**< No sensor type for sensor test */ SENSOR_TAG_ACCELEROMETER = 1, /**< Acceleration sensor */ SENSOR_TAG_GYROSCOPE = 2, /**< Gyroscope sensor */ SENSOR_TAG_PHOTOPLETHYSMOGRAPH = 3, /**< Photoplethysmography sensor */ From a405a11b4a90f432702ef26a0bbc7892143eabe7 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 19 May 2021 10:50:28 +0800 Subject: [PATCH 10/21] =?UTF-8?q?IssueNo=EF=BC=9A#I3RW19=20Description:syn?= =?UTF-8?q?c=20L2=20peripheral=20code=20to=20L1=20Feature=20or=20Bugfix:Bu?= =?UTF-8?q?gfix=20Binary=20Source:=20NO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- model/network/wifi/core/module/wifi_base.c | 47 +++++++++++----------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/model/network/wifi/core/module/wifi_base.c b/model/network/wifi/core/module/wifi_base.c index 072e10b7..6f291138 100644 --- a/model/network/wifi/core/module/wifi_base.c +++ b/model/network/wifi/core/module/wifi_base.c @@ -374,7 +374,7 @@ static int32_t WifiCmdEnableEapol(const RequestContext *context, struct HdfSBuf } eapol.callback = (void *)HdfWifiEventEapolRecv; - eapol.contex = NULL; + eapol.context = NULL; return EnableEapol(netdev, &eapol); } @@ -486,19 +486,19 @@ static int32_t WifiFillHwFeature(struct NetDevice *netdev, WifiHwFeatureData *fe do { uint32_t loop; if (capability->supportedRateCount > MAX_SUPPORTED_RATE) { - HDF_LOGE("%s: bitrates %d out of range", __func__, capability->supportedRateCount); + HDF_LOGE("%s: bitrates %u out of range", __func__, capability->supportedRateCount); ret = HDF_FAILURE; break; } for (loop = 0; loop < capability->supportedRateCount; ++loop) { - HDF_LOGV("%s: supported rate %d", __func__, capability->supportedRates[loop]); + HDF_LOGV("%s: supported rate %u", __func__, capability->supportedRates[loop]); featureData->bitrate[loop] = capability->supportedRates[loop]; } if (capability->bands[IEEE80211_BAND_2GHZ] != NULL) { struct WlanBand *band = capability->bands[IEEE80211_BAND_2GHZ]; if (band->channelCount > WIFI_24G_CHANNEL_NUM) { - HDF_LOGE("%s: channels %d out of range", __func__, band->channelCount); + HDF_LOGE("%s: channels %u out of range", __func__, band->channelCount); ret = HDF_FAILURE; break; } @@ -630,13 +630,10 @@ static int32_t SetNetIfInfo(struct NetDevice *netdev, uint32_t type) static int32_t UnsetNetIfInfo(struct NetDevice *netdev) { - int ret; - (void)netdev->netDeviceIf->stop(netdev); (void)NetIfDhcpStop(netdev); (void)NetIfDhcpsStop(netdev); - ret = NetIfSetStatus(netdev, NETIF_DOWN); - return ret; + return NetIfSetStatus(netdev, NETIF_DOWN); } static void SetNetworkAddr(struct NetDevice *netdev, uint32_t type) @@ -646,13 +643,13 @@ static void SetNetworkAddr(struct NetDevice *netdev, uint32_t type) IpV4Addr gw; if (type == WIFI_IFTYPE_STATION) { - ip.addr = 0x00000000UL; // 0, 0, 0, 0 - netmask.addr = 0x00000000UL; // 0, 0, 0, 0 - gw.addr = 0x00000000UL; // 0, 0, 0, 0 + ip.addr = 0x00000000UL; + netmask.addr = 0x00000000UL; + gw.addr = 0x00000000UL; } else { - ip.addr = 0x010ca8c0UL; // 192, 168, 12, 1 - netmask.addr = 0x00ffffffUL; // 255, 255, 255, 0 - gw.addr = 0x010ca8c0UL; // 192, 168, 12, 1 + ip.addr = 0x010ca8c0UL; + netmask.addr = 0x00ffffffUL; + gw.addr = 0x010ca8c0UL; } if (netdev != NULL) { @@ -662,9 +659,9 @@ static void SetNetworkAddr(struct NetDevice *netdev, uint32_t type) static void UnsetNetworkAddr(struct NetDevice *netdev) { - IpV4Addr ip = { 0x00000000UL }; // 0, 0, 0, 0 - IpV4Addr netmask = { 0x00000000UL }; // 0, 0, 0, 0 - IpV4Addr gw = { 0x00000000UL }; // 0, 0, 0, 0 + IpV4Addr ip = { 0x00000000UL }; + IpV4Addr netmask = { 0x00000000UL }; + IpV4Addr gw = { 0x00000000UL }; if (netdev != NULL) { NetIfSetAddr(netdev, &ip, &netmask, &gw); @@ -1058,9 +1055,7 @@ static int32_t WifiCmdGetIfNamesByChipId(const RequestContext *context, struct H break; } } while (false); - if (ifNames != NULL) { - OsalMemFree(ifNames); - } + OsalMemFree(ifNames); return ret; } @@ -1135,12 +1130,12 @@ static int32_t WifiCmdDoResetChip(const RequestContext *context, struct HdfSBuf } wlanDevice = HdfWlanGetWlanDevice(chipId); - if (wlanDevice == NULL) { - HDF_LOGE("%s: wlanDevice is NULL, not found!", __func__); + if (wlanDevice == NULL || wlanDevice->reset == NULL) { + HDF_LOGE("%s: wlanDevice or wlanDevice->reset is NULL!", __func__); return HDF_FAILURE; } - ret = DeinitDevice(wlanDevice); + ret = HdfWifiDeinitDevice(wlanDevice); if (ret != HDF_SUCCESS) { return ret; } @@ -1152,7 +1147,7 @@ static int32_t WifiCmdDoResetChip(const RequestContext *context, struct HdfSBuf return ERR_POWER_RESET_FAIL; } - ret = InitDevice(wlanDevice); + ret = HdfWifiInitDevice(wlanDevice); return ret; } @@ -1190,6 +1185,10 @@ static int32_t WifiCmdResetDriver(const RequestContext *context, struct HdfSBuf } struct HdfSBuf *data = HdfSBufCopy(reqData); + if (data == NULL) { + HDF_LOGE("%s: sbuf copy fail", __func__); + return HDF_FAILURE; + } ret = g_baseService->SendAsyncMessage(g_baseService, BASE_SERVICE_ID, CMD_BASE_DO_RESET_PRIVATE, data, SendMessageResetDriverCallBack); From d6ee4b17ddcf100c0a89261b9f7d6285d8a0bcc7 Mon Sep 17 00:00:00 2001 From: zianed Date: Wed, 19 May 2021 11:30:01 +0800 Subject: [PATCH 11/21] sync code to l0l1 --- .gitattributes | 0 .gitignore | 4 + OAT.xml | 99 +++++ README.md | 6 +- README_zh.md | 8 +- core/shared/include/hdf_device_info.h | 72 ---- core/shared/src/hdf_device_info.c | 1 - figures/architecture-of-the-hdf.png | Bin 81696 -> 76207 bytes model/network/common/netdevice/net_device.c | 23 +- model/network/wifi/core/hdf_wifi_core.c | 16 +- model/network/wifi/core/hdf_wifi_core.h | 4 +- support/platform/include/emmc_core.h | 6 +- support/platform/include/plat_common.h | 2 +- support/platform/include/plat_log.h | 2 +- support/platform/include/sdio_core.h | 2 +- support/platform/include/watchdog_core.h | 2 +- support/platform/src/gpio_core.c | 6 +- support/platform/src/watchdog_if.c | 1 - support/posix/src/osal_mutex.c | 2 +- support/posix/src/osal_spinlock.c | 108 +++++ support/posix/src/osal_thread.c | 6 +- .../hcs_parser/unittest/hcs_config_test.c | 68 +-- test/unittest/common/hdf_common_test.c | 2 +- test/unittest/common/hdf_main_test.c | 2 +- test/unittest/manager/sample_driver_test.c | 2 - .../wifi/unittest/net/hdf_netbuf_test.c | 4 +- .../wifi/unittest/netdevice/net_device_test.c | 6 +- .../wifi/unittest/qos/flow_control_test.c | 2 +- test/unittest/osal/osal_all_test.c | 20 +- test/unittest/osal/osal_get_case_test.c | 2 +- test/unittest/osal/osal_test_entry.c | 2 +- test/unittest/platform/common/emmc_test.c | 18 +- test/unittest/platform/common/gpio_test.c | 2 +- .../platform/common/i2c_driver_test.c | 16 +- test/unittest/platform/common/i2c_test.c | 12 +- .../platform/common/platform_driver_test.c | 2 +- test/unittest/platform/common/sdio_test.c | 26 +- test/unittest/platform/common/uart_test.c | 16 +- test/unittest/platform/common/watchdog_test.c | 2 +- .../platform/hdf_mipi_dsi_entry_test.c | 2 +- test/unittest/platform/hdf_rtc_entry_test.c | 58 +-- test/unittest/platform/hdf_rtc_entry_test.h | 2 +- test/unittest/sensor/hdf_sensor_test.c | 2 +- test/unittest/wifi/hdf_wifi_test.c | 7 +- test/unittest/wifi/hdf_wifi_test.h | 1 - tools/hc-gen/Makefile | 2 +- tools/hc-gen/README.md | 2 +- tools/hc-gen/bin/hc-gen | Bin 92808 -> 80360 bytes tools/hc-gen/include/hcs_compiler.h | 6 +- tools/hc-gen/include/hcs_decompiler.h | 4 +- tools/hc-gen/include/hcs_file.h | 18 +- tools/hc-gen/include/hcs_gener.h | 4 +- tools/hc-gen/include/hcs_log.h | 14 +- tools/hc-gen/include/hcs_opcode.h | 2 +- tools/hc-gen/include/hcs_option.h | 14 +- tools/hc-gen/src/hcs_ast.c | 25 +- tools/hc-gen/src/hcs_bytecode_gen.c | 15 +- tools/hc-gen/src/hcs_decompile_gen.c | 82 ++-- tools/hc-gen/src/hcs_decompiler.c | 10 +- tools/hc-gen/src/hcs_file.c | 155 ++++--- tools/hc-gen/src/hcs_hexdump.c | 5 +- tools/hc-gen/src/hcs_mem.c | 7 +- tools/hc-gen/src/hcs_middle.c | 19 +- tools/hc-gen/src/hcs_opcode.c | 4 +- tools/hc-gen/src/hcs_option.c | 31 +- tools/hc-gen/src/hcs_parser.c | 2 +- tools/hc-gen/src/hcs_text_gen.c | 397 ++++++------------ 67 files changed, 734 insertions(+), 730 deletions(-) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 OAT.xml create mode 100644 support/posix/src/osal_spinlock.c diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..e69de29b diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..755f09aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.a +*.d +*.cmd diff --git a/OAT.xml b/OAT.xml new file mode 100644 index 00000000..9877bc28 --- /dev/null +++ b/OAT.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index 27cb7c89..e182839b 100644 --- a/README.md +++ b/README.md @@ -156,9 +156,9 @@ For details, see [WLAN Overview](https://gitee.com/openharmony/docs/blob/master drivers\_framework -[drivers\_adapter\_uhdf](https://gitee.com/openharmony/drivers_adapter_uhdf/blob/master/README.md) +[drivers\_adapter](https://gitee.com/openharmony/drivers_adapter/blob/master/README.md) -[drivers\_adapter\_khdf\_linux](https://gitee.com/openharmony/drivers_adapter_uhdf/blob/master/README.md) +[drivers\_adapter\_khdf\_linux](https://gitee.com/openharmony/drivers_adapter_khdf_linux/blob/master/README.md) -[drivers\_adapter\_khdf\_liteos](https://gitee.com/openharmony/drivers_adapter_uhdf/blob/master/README.md) +[drivers\_peripheral](https://gitee.com/openharmony/drivers_peripheral/blob/master/README.md) diff --git a/README_zh.md b/README_zh.md index 9cac9299..ecc7f41f 100644 --- a/README_zh.md +++ b/README_zh.md @@ -156,13 +156,9 @@ HDF驱动框架详细开发请参考[驱动开发指南](https://gitee.com/openh drivers\_framework -[drivers\_adapter\_uhdf](https://gitee.com/openharmony/drivers_adapter_uhdf/blob/master/README_zh.md) +[drivers\_adapter](https://gitee.com/openharmony/drivers_adapter/blob/master/README_zh.md) [drivers\_adapter\_khdf\_linux](https://gitee.com/openharmony/drivers_adapter_khdf_linux/blob/master/README_zh.md) -[drivers\_adapter\_khdf\_liteos](https://gitee.com/openharmony/drivers_adapter_khdf_liteos/blob/master/README_zh.md) - - - -
+[drivers\_peripheral](https://gitee.com/openharmony/drivers_peripheral/blob/master/README_zh.md) diff --git a/core/shared/include/hdf_device_info.h b/core/shared/include/hdf_device_info.h index b77ec148..de2f2984 100755 --- a/core/shared/include/hdf_device_info.h +++ b/core/shared/include/hdf_device_info.h @@ -12,9 +12,6 @@ #include "hdf_device_desc.h" #include "hdf_slist.h" -#define USB_PNP_INFO_MAX_INTERFACES 32 -#define USB_PNP_DEBUG_STRING "" - enum { HDF_SERVICE_UNUSABLE, HDF_SERVICE_USABLE, @@ -39,75 +36,6 @@ struct HdfDeviceInfo { const char *moduleName; const char *svcName; const char *deviceMatchAttr; - const void *private; -}; - -enum UsbPnpNotifyServiceCmd { - USB_PNP_NOTIFY_ADD_INTERFACE, - USB_PNP_NOTIFY_REMOVE_INTERFACE, - USB_PNP_NOTIFY_REPORT_INTERFACE, -}; - -enum UsbPnpNotifyRemoveType { - USB_PNP_NOTIFY_REMOVE_BUS_DEV_NUM, - USB_PNP_NOTIFY_REMOVE_INTERFACE_NUM, -}; - -enum { - USB_PNP_NOTIFY_MATCH_VENDOR = 0x0001, - USB_PNP_NOTIFY_MATCH_PRODUCT = 0x0002, - USB_PNP_NOTIFY_MATCH_DEV_LOW = 0x0004, - USB_PNP_NOTIFY_MATCH_DEV_HIGH = 0x0008, - USB_PNP_NOTIFY_MATCH_DEV_CLASS = 0x0010, - USB_PNP_NOTIFY_MATCH_DEV_SUBCLASS = 0x0020, - USB_PNP_NOTIFY_MATCH_DEV_PROTOCOL = 0x0040, - USB_PNP_NOTIFY_MATCH_INT_CLASS = 0x0080, - USB_PNP_NOTIFY_MATCH_INT_SUBCLASS = 0x0100, - USB_PNP_NOTIFY_MATCH_INT_PROTOCOL = 0x0200, - USB_PNP_NOTIFY_MATCH_INT_NUMBER = 0x0400, -}; - -struct UsbPnpNotifyServiceInfo { - int32_t length; - - int32_t devNum; - int32_t busNum; - - int32_t interfaceLength; - uint8_t interfaceNumber[USB_PNP_INFO_MAX_INTERFACES]; -} __attribute__ ((packed)); - -struct UsbPnpNotifyInterfaceInfo { - uint8_t interfaceClass; - uint8_t interfaceSubClass; - uint8_t interfaceProtocol; - - uint8_t interfaceNumber; -}; - -struct UsbPnpNotifyDeviceInfo { - uint16_t vendorId; - uint16_t productId; - - uint16_t bcdDeviceLow; - uint16_t bcdDeviceHigh; - - uint8_t deviceClass; - uint8_t deviceSubClass; - uint8_t deviceProtocol; -}; - -struct UsbPnpNotifyMatchInfoTable { - uint32_t usbDevAddr; - int32_t devNum; - int32_t busNum; - - struct UsbPnpNotifyDeviceInfo deviceInfo; - - uint8_t removeType; - uint8_t numInfos; - - struct UsbPnpNotifyInterfaceInfo interfaceInfo[USB_PNP_INFO_MAX_INTERFACES]; }; struct HdfDeviceInfo *HdfDeviceInfoNewInstance(void); diff --git a/core/shared/src/hdf_device_info.c b/core/shared/src/hdf_device_info.c index 29653af9..9228d56f 100755 --- a/core/shared/src/hdf_device_info.c +++ b/core/shared/src/hdf_device_info.c @@ -29,7 +29,6 @@ void HdfDeviceInfoConstruct(struct HdfDeviceInfo *deviceInfo) deviceInfo->svcName = NULL; deviceInfo->moduleName = NULL; deviceInfo->deviceMatchAttr = NULL; - deviceInfo->private = NULL; } struct HdfDeviceInfo *HdfDeviceInfoNewInstance() diff --git a/figures/architecture-of-the-hdf.png b/figures/architecture-of-the-hdf.png index 2bd6a1d84c8f3e284fb684a40bddca7286bbeb58..f4eb8c3cb2702c9f1c29b84448174648dbbe0114 100644 GIT binary patch literal 76207 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 XG|jJ72%YjI1OC)i@7~C|j_~~-A33$# literal 81696 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�Sh6LDlCPqb`@CIv4GRB3=zX=d|?( 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 MAX_NETDEVICE_COUNT) { HDF_LOGE("%s error because of not enough space!", __func__); @@ -68,7 +68,6 @@ static struct NetDeviceImpl *InitNetDeviceImpl(NetDevice *nd, NetIfCategory ifCa HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); return NULL; } - (void)memset_s(ndImpl, sizeof(struct NetDeviceImpl), 0, sizeof(struct NetDeviceImpl)); ndImpl->netDevice = nd; if (RegisterNetDeviceImpl(ndImpl) != HDF_SUCCESS) { @@ -100,6 +99,7 @@ static void DeInitNetDeviceImpl(struct NetDeviceImpl *netDeviceImpl) /* last release netDeviceImpl */ OsalMemFree(netDeviceImpl); + netDeviceImpl = NULL; HDF_LOGI("%s success!", __func__); return; } @@ -117,7 +117,7 @@ static struct NetDeviceImpl *GetImplByNetDevice(const struct NetDevice *netDevic } } } - HDF_LOGE("Don't Get Impl by netdevice"); + HDF_LOGE("%s Get Impl by netdevice failed", __func__); return ndImpl; } @@ -125,7 +125,7 @@ struct NetDevice *NetDeviceInit(const char *ifName, uint32_t len, NetIfCategory { NetDevice *netDevice = NULL; struct NetDeviceImpl *ndImpl = NULL; - int32_t index = 0; + uint32_t index = 0; int32_t ret; if ((ifName == NULL) || (strlen(ifName) != len) || (strlen(ifName) > IFNAMSIZ - 1)) { @@ -137,9 +137,8 @@ struct NetDevice *NetDeviceInit(const char *ifName, uint32_t len, NetIfCategory HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); return NULL; } - (void)memset_s(netDevice, sizeof(NetDevice), 0, sizeof(NetDevice)); - if (memcpy_s(netDevice->name, IFNAMSIZ, ifName, len + 1) != EOK) { - HDF_LOGE("%s fail: memcpy_s fail!", __func__); + if (strcpy_s(netDevice->name, IFNAMSIZ, ifName) != EOK) { + HDF_LOGE("%s fail: strcpy_s fail!", __func__); OsalMemFree(netDevice); return NULL; } @@ -318,7 +317,7 @@ static int32_t NetIfRxImpl(const struct NetDevice *netDevice, NetBuf *buff, Rece ProcessingResult ret = PROCESSING_CONTINUE; if (ndImpl == NULL || ndImpl->interFace == NULL || ndImpl->interFace->receive == NULL) { - HDF_LOGE("NetIfRxImpl fail : netdevice not exist!"); + HDF_LOGE("%s: NetIfRxImpl fail : netdevice not exist!", __func__); return HDF_ERR_INVALID_PARAM; } @@ -333,7 +332,7 @@ static int32_t NetIfRxImpl(const struct NetDevice *netDevice, NetBuf *buff, Rece HDF_LOGI("NetIfRxImpl specialEtherType Process not need TCP/IP stack!"); return HDF_SUCCESS; } else { - HDF_LOGE("NetIfRxImpl specialEtherType Process error"); + HDF_LOGE("%s: NetIfRxImpl specialEtherType Process error", __func__); return HDF_FAILURE; } } diff --git a/model/network/wifi/core/hdf_wifi_core.c b/model/network/wifi/core/hdf_wifi_core.c index 32179061..75c26ae9 100644 --- a/model/network/wifi/core/hdf_wifi_core.c +++ b/model/network/wifi/core/hdf_wifi_core.c @@ -39,13 +39,13 @@ int32_t HdfWifiGetBusIdx(void) * @brief as for now, we just support one wlan module in one board cause driver binds to wlan featere * due to that reason, once we detected one chip, we stop rescan. */ -int HdfWlanSdioScan(struct HdfWlanDevice *data, struct HdfConfigWlanBus *busConfig) +int32_t HdfWlanSdioScan(struct HdfWlanDevice *data, struct HdfConfigWlanBus *busConfig) { /* get config vendId, deviceId and chip-name which used in detect match process */ HdfWlanGetSdioTableByConfig(); HdfWlanSdioScanTriggerByBusIndex(busConfig->busIdx); - int ret = HdfWlanGetDetectedChip(data, busConfig); + int32_t ret = HdfWlanGetDetectedChip(data, busConfig); HdfWlanSdioDriverUnReg(); if (ret != HDF_SUCCESS) { return ret; @@ -54,7 +54,7 @@ int HdfWlanSdioScan(struct HdfWlanDevice *data, struct HdfConfigWlanBus *busConf return HDF_SUCCESS; } -static int HdfWifiDriverBind(struct HdfDeviceObject *dev) +static int32_t HdfWifiDriverBind(struct HdfDeviceObject *dev) { ErrorCode errCode; static struct IDeviceIoService wifiService = { @@ -179,7 +179,7 @@ static struct HdfChipDriverFactory *HdfWlanGetDriverFactory(const char *driverNa static int32_t HdfWlanDeinitInterface(struct HdfWlanDevice *device, const char *ifName, struct HdfChipDriverFactory *factory) { - int ret; + int32_t ret; struct NetDevice *netdev = NULL; struct HdfChipDriver *chipDriver = NULL; @@ -369,7 +369,7 @@ static struct HdfWlanDevice *ProbeDevice(struct HdfConfigWlanDevInst *deviceConf return device; } -int32_t DeinitDevice(struct HdfWlanDevice *device) +int32_t HdfWifiDeinitDevice(struct HdfWlanDevice *device) { struct HdfChipDriverFactory *chipDriverFact = NULL; int32_t ret; @@ -394,7 +394,7 @@ int32_t DeinitDevice(struct HdfWlanDevice *device) return HDF_SUCCESS; } -int32_t InitDevice(struct HdfWlanDevice *device) +int32_t HdfWifiInitDevice(struct HdfWlanDevice *device) { int32_t ret; struct HdfChipDriverFactory *chipDriverFact = NULL; @@ -424,7 +424,7 @@ int32_t InitDevice(struct HdfWlanDevice *device) /* thread callback function */ static int32_t HdfWlanInitThread(void *para) { - const uint32_t initDelaySec = 5; + const uint32_t initDelaySec = 15; struct HdfDeviceObject *device = (struct HdfDeviceObject *)para; struct SubscriberCallback callback = { NULL }; struct HdfConfigWlanDeviceList *devList = NULL; @@ -465,7 +465,7 @@ static int32_t HdfWlanInitThread(void *para) // Load chip driver (void)DevSvcManagerClntSubscribeService(wlanDevice->driverName, callback); - (void)InitDevice(wlanDevice); + (void)HdfWifiInitDevice(wlanDevice); } HDF_LOGV("%s:finished.", __func__); diff --git a/model/network/wifi/core/hdf_wifi_core.h b/model/network/wifi/core/hdf_wifi_core.h index c171fd61..78134dc5 100644 --- a/model/network/wifi/core/hdf_wifi_core.h +++ b/model/network/wifi/core/hdf_wifi_core.h @@ -17,9 +17,9 @@ extern "C" { #endif int32_t HdfWifiGetBusIdx(void); -int32_t DeinitDevice(struct HdfWlanDevice *device); +int32_t HdfWifiDeinitDevice(struct HdfWlanDevice *device); -int32_t InitDevice(struct HdfWlanDevice *device); +int32_t HdfWifiInitDevice(struct HdfWlanDevice *device); #ifdef __cplusplus } diff --git a/support/platform/include/emmc_core.h b/support/platform/include/emmc_core.h index 55f835f2..d6730afb 100644 --- a/support/platform/include/emmc_core.h +++ b/support/platform/include/emmc_core.h @@ -6,8 +6,8 @@ * See the LICENSE file in the root of this repository for complete details. */ -#ifndef emmc_CORE_H -#define emmc_CORE_H +#ifndef EMMC_CORE_H +#define EMMC_CORE_H #include "emmc_if.h" #include "hdf_base.h" @@ -39,7 +39,7 @@ struct EmmcCntlr { /** * @brief emmc host device operations. - * These methods need to be filled up by specific paltform. + * These methods need to be filled up by specific platform. */ struct EmmcMethod { int32_t (*getCid)(struct EmmcCntlr *, uint8_t *, uint32_t); diff --git a/support/platform/include/plat_common.h b/support/platform/include/plat_common.h index e10234ec..6610dd57 100644 --- a/support/platform/include/plat_common.h +++ b/support/platform/include/plat_common.h @@ -13,4 +13,4 @@ bool PlatInIrqContext(void); -#endif +#endif /* PLATFORM_COMMON_H */ diff --git a/support/platform/include/plat_log.h b/support/platform/include/plat_log.h index 4de73d19..bc2d0671 100644 --- a/support/platform/include/plat_log.h +++ b/support/platform/include/plat_log.h @@ -17,4 +17,4 @@ #define PLAT_LOGV(fmt, arg...) HDF_LOGV(fmt, ##arg) #endif -#endif +#endif /* PLATFORM_LOG_H */ diff --git a/support/platform/include/sdio_core.h b/support/platform/include/sdio_core.h index 92a8d7cb..ef18b6c5 100644 --- a/support/platform/include/sdio_core.h +++ b/support/platform/include/sdio_core.h @@ -38,7 +38,7 @@ struct SdioCntlr { /** * @brief sdio host device operations. - * These methods need to be filled up by specific paltform. + * These methods need to be filled up by specific platform. */ struct SdioMethod { int32_t (*incrAddrReadBytes)(struct SdioCntlr *, uint8_t *, uint32_t, uint32_t, uint32_t); diff --git a/support/platform/include/watchdog_core.h b/support/platform/include/watchdog_core.h index 43bb1de6..84620473 100644 --- a/support/platform/include/watchdog_core.h +++ b/support/platform/include/watchdog_core.h @@ -45,7 +45,7 @@ struct WatchdogMethod { /** * @brief Add a new WatchdogCntlr to HDF. * - * @param cntlr The watchdog conroller to be added. + * @param cntlr The watchdog controller to be added. * * @return Returns 0 on success; returns a negative value otherwise. * @since 1.0 diff --git a/support/platform/src/gpio_core.c b/support/platform/src/gpio_core.c index eaca5907..7224aeb2 100644 --- a/support/platform/src/gpio_core.c +++ b/support/platform/src/gpio_core.c @@ -212,7 +212,7 @@ static int32_t GpioIrqBridgeFunc(uint16_t local, void *data) (void)local; (void)OsalSpinLockIrqSave(&bridge->spin, &flags); - if (bridge->stop == false) { + if (!bridge->stop) { (void)OsalSemPost(&bridge->sem); } (void)OsalSpinUnlockIrqRestore(&bridge->spin, &flags); @@ -230,7 +230,7 @@ static int GpioIrqThreadWorker(void *data) if (ret != HDF_SUCCESS) { continue; } - if (bridge->stop == true) { + if (bridge->stop) { break; } PLAT_LOGV("GpioIrqThreadWorker: enter! gpio:%u-%u", bridge->cntlr->start, bridge->local); @@ -320,7 +320,7 @@ static void GpioIrqBridgeDestroy(struct GpioIrqBridge *bridge) #ifndef __KERNEL__ uint32_t flags; (void)OsalSpinLockIrqSave(&bridge->spin, &flags); - if (bridge->stop == false) { + if (!bridge->stop) { bridge->stop = true; (void)OsalSemPost(&bridge->sem); } diff --git a/support/platform/src/watchdog_if.c b/support/platform/src/watchdog_if.c index cf317f5f..b67506ee 100644 --- a/support/platform/src/watchdog_if.c +++ b/support/platform/src/watchdog_if.c @@ -46,7 +46,6 @@ static struct Watchdog *WatchdogGetById(int16_t wdtId) return service; } - DevHandle WatchdogOpen(int16_t wdtId) { struct Watchdog *service = NULL; diff --git a/support/posix/src/osal_mutex.c b/support/posix/src/osal_mutex.c index 8ca66662..6769c921 100644 --- a/support/posix/src/osal_mutex.c +++ b/support/posix/src/osal_mutex.c @@ -106,7 +106,7 @@ int32_t OsalMutexTimedLock(struct OsalMutex *mutex, uint32_t ms) if (ret == ETIMEDOUT) { return HDF_ERR_TIMEOUT; } else { - HDF_LOGE("%s time_out time:%d ret:%d", __func__, ms, ret); + HDF_LOGE("%s time_out time:%u ret:%d", __func__, ms, ret); return HDF_FAILURE; } } diff --git a/support/posix/src/osal_spinlock.c b/support/posix/src/osal_spinlock.c new file mode 100644 index 00000000..695623b8 --- /dev/null +++ b/support/posix/src/osal_spinlock.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "osal_spinlock.h" +#include +#include "hdf_log.h" +#include "osal_mem.h" + +#define HDF_LOG_TAG osal_spinlock + +int32_t OsalSpinInit(OsalSpinlock *spinlock) +{ + pthread_spinlock_t *spinTmp = NULL; + int ret; + + if (spinlock == NULL) { + HDF_LOGE("%s invalid param", __func__); + return HDF_ERR_INVALID_PARAM; + } + + spinlock->realSpinlock = NULL; + + spinTmp = (pthread_spinlock_t *)OsalMemCalloc(sizeof(pthread_spinlock_t)); + if (spinTmp == NULL) { + HDF_LOGE("malloc fail"); + return HDF_ERR_MALLOC_FAIL; + } + + ret = pthread_spin_init(spinTmp, PTHREAD_PROCESS_PRIVATE); + if (ret != 0) { + HDF_LOGE("pthread_spin_init fail %d %d", ret, __LINE__); + OsalMemFree(spinTmp); + return HDF_FAILURE; + } + spinlock->realSpinlock = (void *)spinTmp; + + return HDF_SUCCESS; +} + +int32_t OsalSpinDestroy(OsalSpinlock *spinlock) +{ + int ret; + + if (spinlock == NULL || spinlock->realSpinlock == NULL) { + HDF_LOGE("%s invalid param", __func__); + return HDF_ERR_INVALID_PARAM; + } + + ret = pthread_spin_destroy((pthread_spinlock_t *)spinlock->realSpinlock); + if (ret != 0) { + HDF_LOGE("pthread_spin_destroy fail %d %d", ret, __LINE__); + return HDF_FAILURE; + } + + OsalMemFree(spinlock->realSpinlock); + spinlock->realSpinlock = NULL; + + return HDF_SUCCESS; +} + +int32_t OsalSpinLock(OsalSpinlock *spinlock) +{ + int ret; + + if (spinlock == NULL || spinlock->realSpinlock == NULL) { + HDF_LOGE("%s invalid param", __func__); + return HDF_ERR_INVALID_PARAM; + } + + ret = pthread_spin_lock((pthread_spinlock_t *)spinlock->realSpinlock); + if (ret != 0) { + HDF_LOGE("pthread_spin_lock fail %d %d", ret, __LINE__); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +int32_t OsalSpinUnlock(OsalSpinlock *spinlock) +{ + int ret; + + if (spinlock == NULL || spinlock->realSpinlock == NULL) { + HDF_LOGE("%s invalid param", __func__); + return HDF_ERR_INVALID_PARAM; + } + + ret = pthread_spin_unlock((pthread_spinlock_t *)spinlock->realSpinlock); + if (ret != 0) { + HDF_LOGE("pthread_spin_unlock fail %d %d", ret, __LINE__); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + diff --git a/support/posix/src/osal_thread.c b/support/posix/src/osal_thread.c index fc621b42..bdf5e16c 100644 --- a/support/posix/src/osal_thread.c +++ b/support/posix/src/osal_thread.c @@ -12,8 +12,6 @@ #include "hdf_log.h" #include "osal_mem.h" -#define OSAL_PTHREAD_STACK_MIN 4096 - #define HDF_LOG_TAG osal_thread typedef void *(*PosixEntry)(void *data); @@ -75,7 +73,7 @@ int32_t OsalThreadCreate(struct OsalThread *thread, OsalThreadEntry threadEntry, int32_t OsalThreadDestroy(struct OsalThread *thread) { - if (thread->realThread != NULL) { + if (thread != NULL && thread->realThread != NULL) { OsalMemFree(thread->realThread); thread->realThread = NULL; } @@ -129,7 +127,7 @@ int32_t OsalThreadStart(struct OsalThread *thread, const struct OsalThreadParam size_t stackSize = param->stackSize; if (stackSize > 0) { - stackSize = (stackSize < OSAL_PTHREAD_STACK_MIN) ? OSAL_PTHREAD_STACK_MIN : stackSize; + stackSize = (stackSize < PTHREAD_STACK_MIN) ? PTHREAD_STACK_MIN : stackSize; resultCode = pthread_attr_setstacksize(&attribute, stackSize); if (resultCode != 0) { HDF_LOGE("pthread_attr_setstacksize errorno: %d", resultCode); diff --git a/test/unittest/ability/config/hcs_parser/unittest/hcs_config_test.c b/test/unittest/ability/config/hcs_parser/unittest/hcs_config_test.c index 654698f2..cb2ea0c1 100644 --- a/test/unittest/ability/config/hcs_parser/unittest/hcs_config_test.c +++ b/test/unittest/ability/config/hcs_parser/unittest/hcs_config_test.c @@ -258,7 +258,7 @@ int HcsTestGetUint8ArrayElemSuccess(void) { uint8_t data[DATA_TEST_ARRAY_LENGTH] = { 0 }; // the test data is 0, 1, 2, 3, 4, 5, 6, 7. - uint8_t testData[DATA_TEST_ARRAY_LENGTH] = {0, 1, 2, 3, 4, 5, 6, 7}; + uint8_t testData[DATA_TEST_ARRAY_LENGTH] = { 0, 1, 2, 3, 4, 5, 6, 7 }; uint32_t i; if (!TestGetRootNode()) { return HDF_FAILURE; @@ -272,7 +272,7 @@ int HcsTestGetUint8ArrayElemSuccess(void) int32_t ret = g_devResInstance->GetUint8ArrayElem(dataType, TEST_U8_ELEM_DATA, i, &data[i], DEFAULT_UINT8_MAX); if ((ret != HDF_SUCCESS) || (data[i] != testData[i])) { - HDF_LOGE("%s failed, line: %d, ret = %d, i = %d, data = %u", __FUNCTION__, __LINE__, ret, i, data[i]); + HDF_LOGE("%s failed, line: %d, ret = %d, i = %u, data = %u", __FUNCTION__, __LINE__, ret, i, data[i]); return HDF_FAILURE; } } @@ -303,7 +303,7 @@ int HcsTestGetUint8ArrayElemFail(void) for (i = 0; i < count; i++) { ret = g_devResInstance->GetUint8ArrayElem(dataType, READ_FOUR_DATA_TYPE, i, &data1[i], DEFAULT_UINT8_MAX); } - // the 0~3 represents the loction in array. + // the 0~3 represents the location in array. if ((ret == HDF_SUCCESS) || (data1[0] != U8_DATA) || (data1[1] != DEFAULT_UINT8_MAX) || (data1[2] != DEFAULT_UINT8_MAX) || (data1[3] != DEFAULT_UINT8_MAX)) { HDF_LOGE("%s failed, line: %d, ret = %d, data = %x", __FUNCTION__, __LINE__, ret, data); @@ -321,7 +321,7 @@ int HcsTestGetUint8ArraySuccess(void) const struct DeviceResourceNode *dataType = g_devResInstance->GetNodeByMatchAttr(g_testRoot, HW_DATA_TYPE_TEST); int32_t ret = g_devResInstance->GetUint8Array(dataType, TEST_U8_ELEM_DATA, data, DATA_TEST_ARRAY_LENGTH, DEFAULT_UINT8_MAX); - // the 0~7 represents the loction in array or the value in hcs file. + // the 0~7 represents the location in array or the value in hcs file. if ((ret != HDF_SUCCESS) || (data[0] != 0) || (data[1] != 1) || (data[2] != 2) || (data[3] != 3) || (data[4] != 4) || (data[5] != 5) || (data[6] != 6) || (data[7] != 7)) { return HDF_FAILURE; @@ -337,13 +337,13 @@ int HcsTestGetUint8ArrayFail(void) } const struct DeviceResourceNode *dataType = g_devResInstance->GetNodeByMatchAttr(g_testRoot, HW_DATA_TYPE_TEST); int32_t ret = g_devResInstance->GetUint8Array(dataType, READ_FOUR_DATA_TYPE, data, 0, DEFAULT_UINT8_MAX); - // the 0, 1, 2 represents the loction in array, the 0 of second param is defalut value. + // the 0, 1, 2 represents the location in array, the 0 of second param is default value. if ((ret == HDF_SUCCESS) || (data[0] != 0) || (data[1] != 0) || (data[2] != 0)) { return HDF_FAILURE; } ret = g_devResInstance->GetUint8Array(dataType, READ_FOUR_DATA_TYPE, data, DATA_TYPE_NUM_U64 + 1, DEFAULT_UINT8_MAX); - // the 0, 1, 2, 3, 4 represents the loction in array + // the 0, 1, 2, 3, 4 represents the location in array if ((ret == HDF_SUCCESS) || (data[0] != U8_DATA) || (data[1] != DEFAULT_UINT8_MAX) || (data[2] != DEFAULT_UINT8_MAX) || (data[3] != DEFAULT_UINT8_MAX) || (data[4] != DEFAULT_UINT8_MAX)) { return HDF_FAILURE; @@ -402,7 +402,7 @@ int HcsTestGetUint16ArrayElemSuccess(void) // the length of data is 8. uint16_t data[DATA_TEST_ARRAY_LENGTH] = { 0 }; // the test data is 0, 1, 2, 3, 4, 5, 256, 257. - uint16_t testData[DATA_TEST_ARRAY_LENGTH] = {0, 1, 2, 3, 4, 5, 256, 257}; + uint16_t testData[DATA_TEST_ARRAY_LENGTH] = { 0, 1, 2, 3, 4, 5, 256, 257 }; uint32_t i; if (!TestGetRootNode()) { return HDF_FAILURE; @@ -444,7 +444,7 @@ int HcsTestGetUint16ArrayElemFail(void) for (i = 0; i < count; i++) { ret = g_devResInstance->GetUint16ArrayElem(dataType, READ_FOUR_DATA_TYPE, i, &data1[i], DEFAULT_UINT16_MAX); } - // the 0~3 represents the loction in array. + // the 0~3 represents the location in array. if ((ret == HDF_SUCCESS) || (data1[0] != U8_DATA) || (data1[1] != U16_DATA) || (data1[2] != DEFAULT_UINT16_MAX) || (data1[3] != DEFAULT_UINT16_MAX)) { return HDF_FAILURE; @@ -461,7 +461,7 @@ int HcsTestGetUint16ArraySuccess(void) const struct DeviceResourceNode *dataType = g_devResInstance->GetNodeByMatchAttr(g_testRoot, HW_DATA_TYPE_TEST); int32_t ret = g_devResInstance->GetUint16Array(dataType, TEST_U16_ELEM_DATA, data, DATA_TEST_ARRAY_LENGTH, DEFAULT_UINT16_MAX); - // the data[0~7] represents the loction in array, the test data is 0, 1, 2, 3, 4, 5, 256, 257. + // the data[0~7] represents the location in array, the test data is 0, 1, 2, 3, 4, 5, 256, 257. if ((ret != HDF_SUCCESS) || (data[0] != 0) || (data[1] != 1) || (data[2] != 2) || (data[3] != 3) || (data[4] != 4) || (data[5] != 5) || (data[6] != 256) || (data[7] != 257)) { return HDF_FAILURE; @@ -477,13 +477,13 @@ int HcsTestGetUint16ArrayFail(void) } const struct DeviceResourceNode *dataType = g_devResInstance->GetNodeByMatchAttr(g_testRoot, HW_DATA_TYPE_TEST); int32_t ret = g_devResInstance->GetUint16Array(dataType, READ_FOUR_DATA_TYPE, data, 0, DEFAULT_UINT16_MAX); - // the 0, 1, 2 represents the loction in array, the 0 of second param is defalut value. + // the 0, 1, 2 represents the location in array, the 0 of second param is default value. if ((ret == HDF_SUCCESS) || (data[0] != 0) || (data[1] != 0) || (data[2] != 0)) { return HDF_FAILURE; } ret = g_devResInstance->GetUint16Array(dataType, READ_FOUR_DATA_TYPE, data, DATA_TYPE_NUM_U64 + 1, DEFAULT_UINT16_MAX); - // the 0, 1, 2, 3, 4 represents the loction in array + // the 0, 1, 2, 3, 4 represents the location in array if ((ret == HDF_SUCCESS) || (data[0] != U8_DATA) || (data[1] != U16_DATA) || (data[2] != DEFAULT_UINT16_MAX) || (data[3] != DEFAULT_UINT16_MAX) || (data[4] != DEFAULT_UINT16_MAX)) { return HDF_FAILURE; @@ -537,7 +537,7 @@ int HcsTestGetUint32AttrValueFail(void) int HcsTestGetUint32ArrayElemSuccess(void) { uint32_t data[DATA_TYPE_NUM_U32] = { 0 }; - uint32_t testData[DATA_TYPE_NUM_U32] = {U8_DATA, U16_DATA, U32_DATA}; + uint32_t testData[DATA_TYPE_NUM_U32] = { U8_DATA, U16_DATA, U32_DATA }; int32_t i; if (!TestGetRootNode()) { return HDF_FAILURE; @@ -578,7 +578,7 @@ int HcsTestGetUint32ArraySuccess(void) return HDF_FAILURE; } int32_t ret = g_devResInstance->GetUint32Array(g_testRoot, BOARD_ID, data, BOARDID_LENGTH, DEFAULT_UINT32_MAX); - // the 0, 1 represents the loction in array. + // the 0, 1 represents the location in array. if ((ret != HDF_SUCCESS) || (data[0] != U32_DATA) || (data[1] != U16_DATA)) { return HDF_FAILURE; } @@ -592,12 +592,12 @@ int HcsTestGetUint32ArrayFail(void) return HDF_FAILURE; } int32_t ret = g_devResInstance->GetUint32Array(g_testRoot, BOARD_ID, data, 0, DEFAULT_UINT32_MAX); - // the 0, 1, 2 represents the loction in array, the 0 of second param is defalut value. + // the 0, 1, 2 represents the location in array, the 0 of second param is default value. if ((ret == HDF_SUCCESS) || (data[0] != 0) || (data[1] != 0) || (data[2] != 0)) { return HDF_FAILURE; } ret = g_devResInstance->GetUint32Array(g_testRoot, BOARD_ID, data, DATA_TYPE_NUM_U32, DEFAULT_UINT32_MAX); - // the 0, 1, 2 represents the loction in array + // the 0, 1, 2 represents the location in array if ((ret == HDF_SUCCESS) || (data[0] != U32_DATA) || (data[1] != U16_DATA) || (data[2] != DEFAULT_UINT32_MAX)) { return HDF_FAILURE; } @@ -655,7 +655,7 @@ int HcsTestGetUint64AttrValueFail(void) int HcsTestGetUint64ArrayElemSuccess(void) { uint64_t data[DATA_TYPE_NUM_U64] = { 0 }; - uint64_t testData[DATA_TYPE_NUM_U64] = {U8_DATA, U16_DATA, U32_DATA, U64_DATA}; + uint64_t testData[DATA_TYPE_NUM_U64] = { U8_DATA, U16_DATA, U32_DATA, U64_DATA }; uint32_t i; if (!TestGetRootNode()) { return HDF_FAILURE; @@ -699,7 +699,7 @@ int HcsTestGetUint64ArraySuccess(void) const struct DeviceResourceNode *dataType = g_devResInstance->GetNodeByMatchAttr(g_testRoot, HW_DATA_TYPE_TEST); int32_t ret = g_devResInstance->GetUint64Array(dataType, READ_FOUR_DATA_TYPE, data, DATA_TYPE_NUM_U64, DEFAULT_UINT64_MAX); - // the 0, 1, 2 represents the loction in array. + // the 0, 1, 2 represents the location in array. if ((ret != HDF_SUCCESS) || (data[0] != U8_DATA) || (data[1] != U16_DATA) || (data[2] != U32_DATA) || (data[3] != U64_DATA)) { return HDF_FAILURE; @@ -715,13 +715,13 @@ int HcsTestGetUint64ArrayFail(void) } const struct DeviceResourceNode *dataType = g_devResInstance->GetNodeByMatchAttr(g_testRoot, HW_DATA_TYPE_TEST); int32_t ret = g_devResInstance->GetUint64Array(dataType, READ_FOUR_DATA_TYPE, data, 0, DEFAULT_UINT64_MAX); - // the 0, 1, 2 represents the loction in array, the 0 of second param is defalut value. + // the 0, 1, 2 represents the location in array, the 0 of second param is default value. if ((ret == HDF_SUCCESS) || (data[0] != 0) || (data[1] != 0) || (data[2] != 0)) { return HDF_FAILURE; } ret = g_devResInstance->GetUint64Array(dataType, READ_FOUR_DATA_TYPE, data, DATA_TYPE_NUM_U64 + 1, DEFAULT_UINT64_MAX); - // the 0, 1, 2, 3, 4 represents the loction in array + // the 0, 1, 2, 3, 4 represents the location in array if ((ret == HDF_SUCCESS) || (data[0] != U8_DATA) || (data[1] != U16_DATA) || (data[2] != U32_DATA) || (data[3] != U64_DATA) || (data[4] != DEFAULT_UINT64_MAX)) { return HDF_FAILURE; @@ -865,7 +865,7 @@ int HcsTestTraverseAttrInNodeFail(void) const struct DeviceResourceNode *childNode = NULL; DEV_RES_NODE_FOR_EACH_CHILD_NODE(fingerprintNode, childNode) { - if (childNode == NULL) { + if ((childNode == NULL) || (childNode->name == NULL)) { break; } if ((strcmp(childNode->name, "fingerprint_one") == 0) || (strcmp(childNode->name, "fingerprint_two") == 0)) { @@ -886,9 +886,9 @@ int HcsTestGetStringSuccess(void) return HDF_FAILURE; } const struct DeviceResourceNode *audioNode = g_devResInstance->GetNodeByMatchAttr(g_testRoot, HW_AUDIO_INFO); - const char *ptype = NULL; - int32_t readString = g_devResInstance->GetString(audioNode, "cust_name", &ptype, NULL); - if ((readString != HDF_SUCCESS) || (ptype == NULL) || (strcmp(ptype, "audio_custom_v2") != HDF_SUCCESS)) { + const char *type = NULL; + int32_t readString = g_devResInstance->GetString(audioNode, "cust_name", &type, NULL); + if ((readString != HDF_SUCCESS) || (type == NULL) || (strcmp(type, "audio_custom_v2") != HDF_SUCCESS)) { return HDF_FAILURE; } return HDF_SUCCESS; @@ -900,17 +900,17 @@ int HcsTestGetStringFail(void) return HDF_FAILURE; } const struct DeviceResourceNode *audioNode = g_devResInstance->GetNodeByMatchAttr(g_testRoot, HW_AUDIO_INFO); - const char *ptype = NULL; - int32_t testReadString = g_devResInstance->GetString(audioNode, INVALID_STRING, &ptype, STRING_ATTR_VALUE); - if ((testReadString == HDF_SUCCESS) || (ptype == NULL) || (strcmp(ptype, STRING_ATTR_VALUE) != HDF_SUCCESS)) { + const char *type = NULL; + int32_t testReadString = g_devResInstance->GetString(audioNode, INVALID_STRING, &type, STRING_ATTR_VALUE); + if ((testReadString == HDF_SUCCESS) || (type == NULL) || (strcmp(type, STRING_ATTR_VALUE) != HDF_SUCCESS)) { return HDF_FAILURE; } testReadString = g_devResInstance->GetString(audioNode, INVALID_STRING, NULL, STRING_ATTR_VALUE); - if ((testReadString == HDF_SUCCESS) || (ptype == NULL) || (strcmp(ptype, STRING_ATTR_VALUE) != HDF_SUCCESS)) { + if ((testReadString == HDF_SUCCESS) || (type == NULL) || (strcmp(type, STRING_ATTR_VALUE) != HDF_SUCCESS)) { return HDF_FAILURE; } - testReadString = g_devResInstance->GetString(audioNode, INVALID_STRING, &ptype, NULL); - if (testReadString == HDF_SUCCESS || ptype != NULL) { + testReadString = g_devResInstance->GetString(audioNode, INVALID_STRING, &type, NULL); + if ((testReadString == HDF_SUCCESS) || (type != NULL)) { return HDF_FAILURE; } return HDF_SUCCESS; @@ -923,17 +923,17 @@ int HcsTestGetStringArrayElemSuccess(void) } const char *rawDataDts = NULL; const struct DeviceResourceNode *fingerprintNode = g_devResInstance->GetChildNode(g_testRoot, FINGERPRINT_INFO); - // the third param is the loction in string_list_names array. + // the third param(0) is the location in string_list_names array. int32_t ret = g_devResInstance->GetStringArrayElem(fingerprintNode, STRING_LIST_NAMES, 0, &rawDataDts, NULL); if ((ret != HDF_SUCCESS) || (strcmp(rawDataDts, "first") != HDF_SUCCESS)) { return HDF_FAILURE; } - // the third param is the loction in string_list_names array. + // the third param(1) is the location in string_list_names array. ret = g_devResInstance->GetStringArrayElem(fingerprintNode, STRING_LIST_NAMES, 1, &rawDataDts, NULL); if ((ret != HDF_SUCCESS) || (strcmp(rawDataDts, "second") != HDF_SUCCESS)) { return HDF_FAILURE; } - // the second param is 2, indicates the index, the third param is the loction in string_list_names array. + // the third param(2) is the location in string_list_names array. ret = g_devResInstance->GetStringArrayElem(fingerprintNode, STRING_LIST_NAMES, 2, &rawDataDts, NULL); if ((ret != HDF_SUCCESS) || (strcmp(rawDataDts, "third") != HDF_SUCCESS)) { return HDF_FAILURE; @@ -948,14 +948,14 @@ int HcsTestGetStringArrayElemFail(void) } const char *rawDataDts = NULL; const struct DeviceResourceNode *fingerprintNode = g_devResInstance->GetChildNode(g_testRoot, FINGERPRINT_INFO); - // the third param(3) is the loction in string_list_names array. + // the third param(3) is the location in string_list_names array. int32_t ret = g_devResInstance->GetStringArrayElem(fingerprintNode, STRING_LIST_NAMES, 3, &rawDataDts, STRING_ATTR_VALUE); if ((ret == HDF_SUCCESS) || (strcmp(rawDataDts, STRING_ATTR_VALUE) != HDF_SUCCESS)) { return HDF_FAILURE; } - // the third param(1) is the loction in string_list_names array. + // the third param(1) is the location in string_list_names array. ret = g_devResInstance->GetStringArrayElem(fingerprintNode, READ_U32_INDEX, 1, &rawDataDts, STRING_ATTR_VALUE); if ((ret == HDF_SUCCESS) || (strcmp(rawDataDts, STRING_ATTR_VALUE) != HDF_SUCCESS)) { return HDF_FAILURE; diff --git a/test/unittest/common/hdf_common_test.c b/test/unittest/common/hdf_common_test.c index d3c9cf8b..075d51a3 100644 --- a/test/unittest/common/hdf_common_test.c +++ b/test/unittest/common/hdf_common_test.c @@ -69,7 +69,7 @@ int HdfTestSendMsgToService(struct HdfTestMsg *msg) } if (!HdfSbufReadBuffer(g_reply, (const void **)&testReply, &len)) { - printf("HdfTestSendMsgToService g_reply read failed\n\r"); + printf("HdfTestSendMsgToService g_reply read failed\n\r"); } if (testReply == NULL) { diff --git a/test/unittest/common/hdf_main_test.c b/test/unittest/common/hdf_main_test.c index 039fe902..ee5e4008 100644 --- a/test/unittest/common/hdf_main_test.c +++ b/test/unittest/common/hdf_main_test.c @@ -127,7 +127,7 @@ static int32_t HdfTestCaseProcess(struct HdfDeviceIoClient *client, replyMsg.cmd = msg->cmd; replyMsg.subCmd = msg->subCmd; - HDF_LOGE("%s::Hdf test receive cmd: command[%d], subCommand[%d]", __func__, msg->cmd, msg->subCmd); + HDF_LOGE("%s::Hdf test receive cmd: command[%u], subCommand[%u]", __func__, msg->cmd, msg->subCmd); replyMsg.result = HDF_FAILURE; for (i = 0; i < sizeof(g_hdfTestFuncList) / sizeof(g_hdfTestFuncList[0]); ++i) { diff --git a/test/unittest/manager/sample_driver_test.c b/test/unittest/manager/sample_driver_test.c index eac190dc..bf69825f 100644 --- a/test/unittest/manager/sample_driver_test.c +++ b/test/unittest/manager/sample_driver_test.c @@ -12,12 +12,10 @@ #define HDF_LOG_TAG sample_driver_test -#define SAMPLE_WRITE_READ 123 #ifndef INT32_MAX #define INT32_MAX 0x7fffffff #endif - void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) { (void)deviceObject; diff --git a/test/unittest/model/network/wifi/unittest/net/hdf_netbuf_test.c b/test/unittest/model/network/wifi/unittest/net/hdf_netbuf_test.c index 76c57ff6..e82ab80d 100644 --- a/test/unittest/model/network/wifi/unittest/net/hdf_netbuf_test.c +++ b/test/unittest/model/network/wifi/unittest/net/hdf_netbuf_test.c @@ -860,7 +860,7 @@ pTestCaseFunc g_hdfNetBufQueueTestCaseLists[] = { HdfNetBufQueueTest009, }; -// HDFNetBuf test canse Entry +// HDFNetBuf test case Entry int32_t HdfNetBufTest(void) { int32_t ret, i; @@ -879,7 +879,7 @@ int32_t HdfNetBufTest(void) return HDF_SUCCESS; } -// HdfNetBufQueue test canse Entry +// HdfNetBufQueue test case Entry int32_t HdfNetBufQueueTest(void) { int32_t ret, i; diff --git a/test/unittest/model/network/wifi/unittest/netdevice/net_device_test.c b/test/unittest/model/network/wifi/unittest/netdevice/net_device_test.c index d44f0036..5d47a211 100644 --- a/test/unittest/model/network/wifi/unittest/netdevice/net_device_test.c +++ b/test/unittest/model/network/wifi/unittest/netdevice/net_device_test.c @@ -21,7 +21,10 @@ static bool WiFiNetDeviceTestEnv(void) { if (g_netDevice == NULL) { char devName[IFNAMSIZ] = {0}; - strncpy_s(devName, IFNAMSIZ, "wlan_test_0", strlen("wlan_test_0") + 1); + if (strncpy_s(devName, IFNAMSIZ, "wlan_test_0", strlen("wlan_test_0") + 1) != EOK) { + HDF_LOGE("%s: strcpy_s fail", __func__); + return false; + } g_netDevice = NetDeviceInit(devName, strlen(devName), LITE_OS); if (g_netDevice == NULL) { HDF_LOGE("%s fail ", __func__); @@ -117,6 +120,7 @@ int32_t WiFiNetDviceTestSetAddr(void) int32_t WiFiNetDviceTestRx(void) { NetBuf *buff = NULL; + int count = sizeof(g_filterData); buff = NetBufAlloc(count); if (buff == NULL) { diff --git a/test/unittest/model/network/wifi/unittest/qos/flow_control_test.c b/test/unittest/model/network/wifi/unittest/qos/flow_control_test.c index 1a4a0ba2..3b880ebf 100644 --- a/test/unittest/model/network/wifi/unittest/qos/flow_control_test.c +++ b/test/unittest/model/network/wifi/unittest/qos/flow_control_test.c @@ -154,7 +154,7 @@ int32_t WiFiFlowControlTestSendData(void) return HDF_FAILURE; } if (g_flowControlInstance->interface == NULL) { - HDF_LOGE("%s interface =null!", __func__); + HDF_LOGE("%s interface = null!", __func__); return HDF_FAILURE; } id = g_flowControlInstance->interface->getQueueIdByEtherBuff(buff); diff --git a/test/unittest/osal/osal_all_test.c b/test/unittest/osal/osal_all_test.c index 1efe4a73..2fa37275 100644 --- a/test/unittest/osal/osal_all_test.c +++ b/test/unittest/osal/osal_all_test.c @@ -158,7 +158,7 @@ int ThreadTest2(void *arg) OsalGetTime(&hdfTs2); OsalDiffTime(&hdfTs1, &hdfTs2, &hdfTsDiff); if (cnt % HDF_THREAD_TEST_MUX_CNT == 0) { - HDF_LOGE("%s %ds %dus", __func__, + HDF_LOGE("%s %us %uus", __func__, (uint32_t)hdfTsDiff.sec, (uint32_t)hdfTsDiff.usec); } if (g_testEndFlag) { @@ -345,7 +345,7 @@ static void OsaFWTest(int flag) (void)memset_s(&fw, sizeof(fw), 0, sizeof(fw)); ret = OsalRequestFirmware(&fw, name, NULL); UT_TEST_CHECK_RET(ret != HDF_SUCCESS, OSAL_FW_REQUEST); - HDF_LOGE("%s %d", name, fw.fwSize); + HDF_LOGE("%s %u", name, fw.fwSize); (void)memset_s(&block, sizeof(block), 0, sizeof(block)); ret = OsalReadFirmware(&fw, &block); @@ -355,10 +355,10 @@ static void OsaFWTest(int flag) #if defined(__LITEOS__) ret = OsalSeekFirmware(&fw, HDF_FILE_SEEK_TEST); UT_TEST_CHECK_RET(ret != HDF_SUCCESS, OSAL_FW_SEEK); - HDF_LOGE("%s %d %d", name, block.dataSize, block.curOffset); + HDF_LOGE("%s %u %d", name, block.dataSize, block.curOffset); ret = OsalReadFirmware(&fw, &block); UT_TEST_CHECK_RET(ret != HDF_SUCCESS, OSAL_FW_READ); - HDF_LOGE("%s %d %d", name, block.dataSize, block.curOffset); + HDF_LOGE("%s %u %d", name, block.dataSize, block.curOffset); fwBuf += HDF_FILE_SEEK_TEST; UT_TEST_CHECK_RET(memcmp(block.data, fwBuf, block.dataSize) != 0, OSAL_FW_DATA_CHECK); #endif @@ -367,8 +367,6 @@ static void OsaFWTest(int flag) ret = OsalReadFirmware(&fw, &block); UT_TEST_CHECK_RET(ret == HDF_SUCCESS, OSAL_FW_READ_AFTER_RELEASE); HDF_LOGE("[OSAL_UT_TEST]%s end", __func__); - - return; } #define THREAD_TEST_TIMER_RUN 20 @@ -542,8 +540,6 @@ void OsaThreadTest1(void) UT_TEST_CHECK_RET(ret != HDF_SUCCESS, OSAL_THREAD_CREATE); ret = OsalThreadStart(&thread, &threadCfg); UT_TEST_CHECK_RET(ret != HDF_SUCCESS, OSAL_THREAD_CREATE); - - return; } void OsaThreadTest(void) @@ -601,27 +597,27 @@ static void OsaTimeTest(void) ret = OsalGetTime(&hdfTs2); UT_TEST_CHECK_RET(ret != HDF_SUCCESS, OSAL_TIME_GETTIME); ret = OsalDiffTime(&hdfTs, &hdfTs2, &hdfTsDiff); - HDF_LOGE("%s %ds %dus", __func__, (uint32_t)hdfTsDiff.sec, (uint32_t)hdfTsDiff.usec); + HDF_LOGE("%s %us %uus", __func__, (uint32_t)hdfTsDiff.sec, (uint32_t)hdfTsDiff.usec); UT_TEST_CHECK_RET(!OsalCheckTime(&hdfTsDiff, TIME_TEST_SLEEP_S * HDF_KILO_UNIT), OSAL_TIME_DIFFTIME); OsalGetTime(&hdfTs); OsalUDelay(TIME_TEST_SLEEP_MS); (void)OsalGetTime(&hdfTs2); (void)OsalDiffTime(&hdfTs, &hdfTs2, &hdfTsDiff); - HDF_LOGE("%s %ds %dus", __func__, (uint32_t)hdfTsDiff.sec, (uint32_t)hdfTsDiff.usec); + HDF_LOGE("%s %us %uus", __func__, (uint32_t)hdfTsDiff.sec, (uint32_t)hdfTsDiff.usec); OsalGetTime(&hdfTs); OsalMDelay(TIME_TEST_SLEEP_MS); (void)OsalGetTime(&hdfTs2); (void)OsalDiffTime(&hdfTs, &hdfTs2, &hdfTsDiff); - HDF_LOGE("%s %ds %dus", __func__, (uint32_t)hdfTsDiff.sec, (uint32_t)hdfTsDiff.usec); + HDF_LOGE("%s %us %uus", __func__, (uint32_t)hdfTsDiff.sec, (uint32_t)hdfTsDiff.usec); OsalGetTime(&hdfTs); OsalMSleep(TIME_TEST_SLEEP_MS); ret = OsalGetTime(&hdfTs2); UT_TEST_CHECK_RET(ret != HDF_SUCCESS, OSAL_TIME_GETTIME); ret = OsalDiffTime(&hdfTs, &hdfTs2, &hdfTsDiff); - HDF_LOGE("%s %ds %dus", __func__, (uint32_t)hdfTsDiff.sec, (uint32_t)hdfTsDiff.usec); + HDF_LOGE("%s %us %uus", __func__, (uint32_t)hdfTsDiff.sec, (uint32_t)hdfTsDiff.usec); UT_TEST_CHECK_RET(ret != HDF_SUCCESS, OSAL_TIME_DIFFTIME); UT_TEST_CHECK_RET(!OsalCheckTime(&hdfTsDiff, TIME_TEST_SLEEP_MS), OSAL_TIME_DIFFTIME); } diff --git a/test/unittest/osal/osal_get_case_test.c b/test/unittest/osal/osal_get_case_test.c index 4a2db735..25b87dff 100644 --- a/test/unittest/osal/osal_get_case_test.c +++ b/test/unittest/osal/osal_get_case_test.c @@ -11,7 +11,7 @@ int OsalGetTestResult(uint32_t cmd) { - HDF_LOGD("[OSAL_UT_TEST]%s %d start", __func__, cmd); + HDF_LOGD("[OSAL_UT_TEST]%s %u start", __func__, cmd); return OSAL_TEST_CASE_CHECK(cmd); } diff --git a/test/unittest/osal/osal_test_entry.c b/test/unittest/osal/osal_test_entry.c index c53b3303..922e2f52 100644 --- a/test/unittest/osal/osal_test_entry.c +++ b/test/unittest/osal/osal_test_entry.c @@ -29,7 +29,7 @@ int32_t HdfOsalEntry(HdfTestMsg *msg) return HDF_FAILURE; } - HDF_LOGD("HdfTest:osal test result[%s-%d %d]", ((result != 0) ? "failed" : "pass"), result, msg->subCmd); + HDF_LOGD("HdfTest:osal test result[%s-%d %u]", ((result != 0) ? "failed" : "pass"), result, msg->subCmd); msg->result = (result != 0) ? HDF_FAILURE : HDF_SUCCESS; return HDF_SUCCESS; diff --git a/test/unittest/platform/common/emmc_test.c b/test/unittest/platform/common/emmc_test.c index 02dc29db..9aaab3e4 100644 --- a/test/unittest/platform/common/emmc_test.c +++ b/test/unittest/platform/common/emmc_test.c @@ -46,7 +46,7 @@ static int32_t TestEmmcGetCid(struct EmmcTester *tester) ret = EmmcGetCid(tester->handle, cid, EMMC_CID_LEN); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: EmmcGetCid fail! ret=%d.", __func__, ret); + HDF_LOGE("%s: EmmcGetCid failed ret=%d.", __func__, ret); return HDF_FAILURE; } for (i = 0; i < EMMC_CID_LEN; i++) { @@ -62,7 +62,7 @@ struct EmmcTestFunc g_emmcTestFunc[] = { static int32_t EmmcTestEntry(struct EmmcTester *tester, int32_t cmd) { int32_t i; - int32_t ret; + int32_t ret = HDF_SUCCESS; bool isFind = false; if (tester == NULL) { @@ -71,7 +71,7 @@ static int32_t EmmcTestEntry(struct EmmcTester *tester, int32_t cmd) } tester->handle = EmmcTestGetHandle(tester); if (tester->handle == NULL) { - HDF_LOGE("%s: emmc test get handle fail", __func__); + HDF_LOGE("%s: emmc test get handle failed", __func__); return HDF_FAILURE; } for (i = 0; i < sizeof(g_emmcTestFunc) / sizeof(g_emmcTestFunc[0]); i++) { @@ -81,9 +81,9 @@ static int32_t EmmcTestEntry(struct EmmcTester *tester, int32_t cmd) break; } } - if (isFind == false) { + if (!isFind) { ret = HDF_ERR_NOT_SUPPORT; - HDF_LOGE("%s: cmd %d not support", __func__, cmd); + HDF_LOGE("%s: cmd %d not supported", __func__, cmd); } EmmcTestReleaseHandle(tester->handle); return ret; @@ -96,19 +96,19 @@ static int32_t EmmcTestFillConfig(struct EmmcTester *tester, const struct Device drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); if (drsOps == NULL || drsOps->GetUint32 == NULL) { - HDF_LOGE("%s: invalid drs ops fail!", __func__); + HDF_LOGE("%s: invalid drs ops", __func__); return HDF_FAILURE; } ret = drsOps->GetUint32(node, "busNum", &(tester->busNum), 0); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: fill bus num fail!", __func__); + HDF_LOGE("%s: fill bus num failed", __func__); return ret; } ret = drsOps->GetUint32(node, "hostId", &(tester->hostId), 0); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: fill hostId fail!", __func__); + HDF_LOGE("%s: fill hostId failed", __func__); return ret; } @@ -147,7 +147,7 @@ static int32_t EmmcTestInit(struct HdfDeviceObject *device) } ret = EmmcTestFillConfig(tester, device->property); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read config fail!", __func__); + HDF_LOGE("%s: read config failed", __func__); return ret; } tester->TestEntry = EmmcTestEntry; diff --git a/test/unittest/platform/common/gpio_test.c b/test/unittest/platform/common/gpio_test.c index 7600efd6..658291b7 100644 --- a/test/unittest/platform/common/gpio_test.c +++ b/test/unittest/platform/common/gpio_test.c @@ -195,7 +195,7 @@ static int32_t TestCaseGpioIrq(struct GpioTester *tester, uint16_t mode, bool in } #endif if (tester->irqCnt <= 0) { - HDF_LOGE("%s: mode:%x on %u fail!", __func__, mode, tester->gpioIrq); + HDF_LOGE("%s: set mode:%x on %u failed", __func__, mode, tester->gpioIrq); return HDF_FAILURE; } return HDF_SUCCESS; diff --git a/test/unittest/platform/common/i2c_driver_test.c b/test/unittest/platform/common/i2c_driver_test.c index e5e28545..ed88adfb 100644 --- a/test/unittest/platform/common/i2c_driver_test.c +++ b/test/unittest/platform/common/i2c_driver_test.c @@ -24,7 +24,7 @@ static int32_t I2cTestDispatch(struct HdfDeviceIoClient *client, int cmd, struct return HDF_ERR_INVALID_PARAM; } if (!HdfSbufWriteBuffer(reply, &g_config, sizeof(g_config))) { - HDF_LOGE("%s: writ reply fail!", __func__); + HDF_LOGE("%s: write reply failed", __func__); return HDF_ERR_IO; } } else { @@ -41,37 +41,37 @@ static int32_t I2cTestReadConfig(struct I2cTestConfig *config, const struct Devi drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); if (drsOps == NULL || drsOps->GetUint32 == NULL) { - HDF_LOGE("%s: invalid drs ops fail!", __func__); + HDF_LOGE("%s: invalid drs ops", __func__); return HDF_FAILURE; } ret = drsOps->GetUint16(node, "bus_num", &config->busNum, 0); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read bus num fail!", __func__); + HDF_LOGE("%s: read bus num failed", __func__); return ret; } ret = drsOps->GetUint16(node, "dev_addr", &config->devAddr, 0); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read dev addr fail!", __func__); + HDF_LOGE("%s: read dev addr failed", __func__); return ret; } ret = drsOps->GetUint16(node, "reg_len", &config->regLen, 1); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read reg len fail!", __func__); + HDF_LOGE("%s: read reg len failed", __func__); return ret; } ret = drsOps->GetUint16(node, "reg_addr", &config->regAddr, 0); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read reg addr fail!", __func__); + HDF_LOGE("%s: read reg addr failed", __func__); return ret; } ret = drsOps->GetUint16(node, "buf_size", &config->bufSize, 0); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read buf size fail!", __func__); + HDF_LOGE("%s: read buf size failed", __func__); return ret; } @@ -90,7 +90,7 @@ static int32_t I2cTestBind(struct HdfDeviceObject *device) ret = I2cTestReadConfig(&g_config, device->property); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read config fail!", __func__); + HDF_LOGE("%s: read config failed", __func__); return ret; } diff --git a/test/unittest/platform/common/i2c_test.c b/test/unittest/platform/common/i2c_test.c index 47801f6e..cba586b2 100644 --- a/test/unittest/platform/common/i2c_test.c +++ b/test/unittest/platform/common/i2c_test.c @@ -23,7 +23,7 @@ #define I2C_TEST_BUF_SIZE_MAX 128 #define I2C_TEST_REG_LEN 2 #define I2C_TEST_MLTTHD_TIMES 1000 -#define I2C_TEST_STACK_SIZE (1024*100) +#define I2C_TEST_STACK_SIZE (1024 * 100) #define I2C_TEST_WAIT_TIMES 200 static struct I2cMsg g_msgs[I2C_TEST_MSG_NUM]; @@ -84,7 +84,7 @@ struct I2cTester *I2cTesterGet(void) static struct I2cTester tester; static bool hasInit = false; - if (hasInit == true) { + if (hasInit) { return &tester; } @@ -96,7 +96,7 @@ struct I2cTester *I2cTesterGet(void) tester.handle = I2cOpen(tester.config.busNum); if (tester.handle == NULL) { - HDF_LOGE("I2cTesterGet: open i2cBus:%u fail! handle:%p", tester.config.busNum, tester.handle); + HDF_LOGE("I2cTesterGet: open i2cBus:%u fail!", tester.config.busNum); return NULL; } @@ -217,14 +217,14 @@ int32_t I2cTestWriteRead(void) return HDF_SUCCESS; } -static int I2cTestThreadFunc(void *parm) +static int I2cTestThreadFunc(void *param) { int32_t i, ret; struct I2cTester *tester = NULL; tester = I2cTesterGet(); if (tester == NULL || tester->handle == NULL) { - *((int32_t *)parm) = 1; + *((int32_t *)param) = 1; return HDF_ERR_INVALID_OBJECT; } @@ -239,7 +239,7 @@ static int I2cTestThreadFunc(void *parm) } } - *((int32_t *)parm) = 1; + *((int32_t *)param) = 1; return HDF_SUCCESS; } diff --git a/test/unittest/platform/common/platform_driver_test.c b/test/unittest/platform/common/platform_driver_test.c index 55917a14..832be851 100644 --- a/test/unittest/platform/common/platform_driver_test.c +++ b/test/unittest/platform/common/platform_driver_test.c @@ -24,7 +24,7 @@ static void DoAllPlatformTest(void) static int32_t PlatformTestBind(struct HdfDeviceObject *device) { - struct IDeviceIoService service; + static struct IDeviceIoService service; if (device == NULL) { HDF_LOGE("%s: device is null!", __func__); diff --git a/test/unittest/platform/common/sdio_test.c b/test/unittest/platform/common/sdio_test.c index 800afbf8..f661c3fc 100644 --- a/test/unittest/platform/common/sdio_test.c +++ b/test/unittest/platform/common/sdio_test.c @@ -60,13 +60,13 @@ static int32_t TestSdioIncrAddrReadAndWriteOtherBytes(struct SdioTester *tester) HDF_LOGE("%s: SdioReadBytes fail! ret=%d.", __func__, ret); return HDF_FAILURE; } - HDF_LOGE("%s: read, data[0]:%d\n", __func__, data[0]); + HDF_LOGE("%s: read, data[0]:%u\n", __func__, data[0]); ret = SdioWriteBytes(tester->handle, &data[0], addr, 1, 0); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: SdioWriteBytes fail! ret=%d.", __func__, ret); return HDF_FAILURE; } - HDF_LOGE("%s: write, data[0]:%d\n", __func__, data[0]); + HDF_LOGE("%s: write, data[0]:%u\n", __func__, data[0]); return HDF_SUCCESS; } @@ -98,7 +98,7 @@ static int32_t TestSdioIncrAddrReadAndWriteOneByte(struct SdioTester *tester) HDF_LOGE("%s: SdioReadBytes fail! ret=%d.", __func__, ret); return HDF_FAILURE; } - HDF_LOGE("%s: read, val:%d.", __func__, val); + HDF_LOGE("%s: read, val:%u.", __func__, val); /* read 1 bits */ addr++; ret = SdioReadBytes(tester->handle, &val, addr, 1, 0); @@ -106,7 +106,7 @@ static int32_t TestSdioIncrAddrReadAndWriteOneByte(struct SdioTester *tester) HDF_LOGE("%s: SdioReadBytes fail! ret=%d.", __func__, ret); return HDF_FAILURE; } - HDF_LOGE("%s: read, val:%d.", __func__, val); + HDF_LOGE("%s: read, val:%u.", __func__, val); return HDF_SUCCESS; } @@ -144,14 +144,14 @@ static int32_t TestSdioFixedAddrReadAndWriteOtherBytes(struct SdioTester *tester HDF_LOGE("%s: SdioReadBytesFromFixedAddr fail! ret=%d.", __func__, ret); return HDF_FAILURE; } - HDF_LOGE("%s: read, data[0]:%d, data[1]:%d\n", __func__, data[0], data[1]); + HDF_LOGE("%s: read, data[0]:%u, data[1]:%u\n", __func__, data[0], data[1]); /* write bits */ ret = SdioWriteBytes(tester->handle, &data[0], addr, 1, 0); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: SdioWriteBytesToFixedAddr fail! ret=%d.", __func__, ret); return HDF_FAILURE; } - HDF_LOGE("%s: write, data[0]:%d, data[1]:%d.", __func__, data[0], data[1]); + HDF_LOGE("%s: write, data[0]:%u, data[1]:%u.", __func__, data[0], data[1]); return ret; } @@ -250,7 +250,7 @@ static int32_t TestSdioFunc0ReadAndWriteBytes(struct SdioTester *tester) } SdioReleaseHost(tester->handle); - HDF_LOGE("%s: Func0 Read, val :%d.", __func__, val); + HDF_LOGE("%s: Func0 Read, val:%u.", __func__, val); return ret; } @@ -264,7 +264,7 @@ static int32_t TestSdioSetAndGetFuncInfo(struct SdioTester *tester) HDF_LOGE("%s: SdioGetCommonInfo fail! ret=%d.", __func__, ret); return ret; } - HDF_LOGE("%s: succ! Timeout=%d.", __func__, info.funcInfo.enTimeout); + HDF_LOGE("%s: succ! Timeout=%u.", __func__, info.funcInfo.enTimeout); info.funcInfo.enTimeout = TEST_TIME_OUT; ret = SdioSetCommonInfo(tester->handle, &info, SDIO_FUNC_INFO); @@ -278,7 +278,7 @@ static int32_t TestSdioSetAndGetFuncInfo(struct SdioTester *tester) HDF_LOGE("%s: SdioGetCommonInfo fail! ret=%d.", __func__, ret); return ret; } - HDF_LOGE("%s: again succ! Timeout=%d.", __func__, info.funcInfo.enTimeout); + HDF_LOGE("%s: again succ! Timeout=%u.", __func__, info.funcInfo.enTimeout); return HDF_SUCCESS; } @@ -355,7 +355,7 @@ struct SdioTestFunc g_sdioTestFunc[] = { static int32_t SdioTestEntry(struct SdioTester *tester, int32_t cmd) { int32_t i; - int32_t ret; + int32_t ret = HDF_SUCCESS; bool isFind = false; if (tester == NULL) { @@ -374,7 +374,7 @@ static int32_t SdioTestEntry(struct SdioTester *tester, int32_t cmd) break; } } - if (isFind == false) { + if (!isFind) { ret = HDF_ERR_NOT_SUPPORT; HDF_LOGE("%s: cmd %d not support", __func__, cmd); } @@ -415,8 +415,8 @@ static int32_t SdioTestFillConfig(struct SdioTester *tester, const struct Device return ret; } - HDF_LOGE("%s: busNum:%d, funcNum:%d, vendorId:0x%x, deviceId:0x%x.", __func__, - tester->busNum, tester->funcNum, tester->vendorId, tester->deviceId); + HDF_LOGE("%s: busNum:%u, funcNum:%u, vendorId:0x%x.", __func__, + tester->busNum, tester->funcNum, tester->vendorId); return HDF_SUCCESS; } diff --git a/test/unittest/platform/common/uart_test.c b/test/unittest/platform/common/uart_test.c index 8808232f..ea7f59ff 100644 --- a/test/unittest/platform/common/uart_test.c +++ b/test/unittest/platform/common/uart_test.c @@ -62,7 +62,7 @@ static int32_t UartGetBaudTest(struct UartTest *test) HDF_LOGE("%s: error", __func__); return HDF_FAILURE; } - HDF_LOGE("%s: baud %d", __func__, baud); + HDF_LOGE("%s: baud %u", __func__, baud); HDF_LOGE("%s: success", __func__); return HDF_SUCCESS; } @@ -94,13 +94,13 @@ static int32_t UartGetAttributeTest(struct UartTest *test) HDF_LOGE("%s: error", __func__); return HDF_FAILURE; } - HDF_LOGE("dataBits %d", attribute.dataBits); - HDF_LOGE("parity %d", attribute.parity); - HDF_LOGE("stopBits %d", attribute.stopBits); - HDF_LOGE("rts %d", attribute.rts); - HDF_LOGE("cts %d", attribute.cts); - HDF_LOGE("fifoRxEn %d", attribute.fifoRxEn); - HDF_LOGE("fifoTxEn %d", attribute.fifoTxEn); + HDF_LOGE("dataBits %u", attribute.dataBits); + HDF_LOGE("parity %u", attribute.parity); + HDF_LOGE("stopBits %u", attribute.stopBits); + HDF_LOGE("rts %u", attribute.rts); + HDF_LOGE("cts %u", attribute.cts); + HDF_LOGE("fifoRxEn %u", attribute.fifoRxEn); + HDF_LOGE("fifoTxEn %u", attribute.fifoTxEn); HDF_LOGE("%s: success", __func__); return HDF_SUCCESS; } diff --git a/test/unittest/platform/common/watchdog_test.c b/test/unittest/platform/common/watchdog_test.c index 7d76b86b..ee2d9236 100644 --- a/test/unittest/platform/common/watchdog_test.c +++ b/test/unittest/platform/common/watchdog_test.c @@ -186,7 +186,7 @@ static int32_t TestCaseWatchdogReliability(struct WatchdogTester *tester) (void)WatchdogSetTimeout(NULL, WATCHDOG_TEST_TIMEOUT); /* invalid device handle */ (void)WatchdogGetTimeout(NULL, &timeout); - /* invalid timout pointer */ + /* invalid timeout pointer */ (void)WatchdogGetTimeout(tester->handle, NULL); HDF_LOGE("%s: test dfr for WatchdogFeed ...", __func__); diff --git a/test/unittest/platform/hdf_mipi_dsi_entry_test.c b/test/unittest/platform/hdf_mipi_dsi_entry_test.c index aab32cbf..c4001c21 100644 --- a/test/unittest/platform/hdf_mipi_dsi_entry_test.c +++ b/test/unittest/platform/hdf_mipi_dsi_entry_test.c @@ -23,7 +23,7 @@ int32_t HdfMipiDsiEntry(HdfTestMsg *msg) test = MipiDsiTestServiceGet(); if (test == NULL) { - HDF_LOGE("%s: get servie fail!\n", __func__); + HDF_LOGE("%s: get service fail!", __func__); return HDF_FAILURE; } diff --git a/test/unittest/platform/hdf_rtc_entry_test.c b/test/unittest/platform/hdf_rtc_entry_test.c index 1285bf9c..640bae98 100644 --- a/test/unittest/platform/hdf_rtc_entry_test.c +++ b/test/unittest/platform/hdf_rtc_entry_test.c @@ -36,7 +36,7 @@ static int8_t g_rtcIrqCallback = HDF_FAILURE; int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) { if (alarmIndex == RTC_ALARM_INDEX_A) { - HDF_LOGE("RtcAlarmACallback alarm a success"); + HDF_LOGE("RtcAlarmACallback: alarm a callback success"); g_rtcIrqCallback = HDF_SUCCESS; } else { g_rtcIrqCallback = HDF_FAILURE; @@ -87,14 +87,14 @@ static int32_t RtcReadWriteTimeTest(struct RtcTime *writeTime) } ret = RtcWriteTime(g_rtcHandle, writeTime); if (ret != 0) { - HDF_LOGE("RtcReadWriteTimeTest write fail"); + HDF_LOGE("RtcReadWriteTimeTest write failed"); return -1; } OsalMSleep(RTC_TEST_WR_WAIT_MS); ret = RtcReadTime(g_rtcHandle, &readTime); if (ret != 0) { - HDF_LOGE("RtcReadWriteTimeTest read fail"); + HDF_LOGE("RtcReadWriteTimeTest read failed"); return -1; } @@ -116,14 +116,14 @@ static int32_t RtcReadWriteAlarmTimeTest(struct RtcTime *writeTime) ret = RtcWriteAlarm(g_rtcHandle, RTC_ALARM_INDEX_A, writeTime); if (ret != 0) { - HDF_LOGE("RtcReadWriteAlarmTimeTest write fail"); + HDF_LOGE("RtcReadWriteAlarmTimeTest write failed"); return -1; } OsalMSleep(RTC_TEST_WR_WAIT_MS); ret = RtcReadAlarm(g_rtcHandle, RTC_ALARM_INDEX_A, &readTime); if (ret != 0) { - HDF_LOGE("RtcReadWriteAlarmTimeTest read fail"); + HDF_LOGE("RtcReadWriteAlarmTimeTest read failed"); return -1; } @@ -152,7 +152,7 @@ static int32_t RtcReadWriteTime(void) ret = RtcReadWriteTimeTest(&tm); if (ret != 0) { - HDF_LOGE("RtcReadWriteTime fail"); + HDF_LOGE("RtcReadWriteTime failed"); return -1; } @@ -176,7 +176,7 @@ static int32_t RtcReadWriteMaxTime(void) tm.weekday = weekday; ret = RtcReadWriteTimeTest(&tm); if (ret == 0) { - HDF_LOGE("RtcReadWriteMaxTime fail"); + HDF_LOGE("RtcReadWriteMaxTime failed"); return -1; } @@ -200,7 +200,7 @@ static int32_t RtcReadWriteMinTime(void) tm.weekday = weekday; ret = RtcReadWriteTimeTest(&tm); if (ret == 0) { - HDF_LOGE("RtcReadWriteMinTime fail"); + HDF_LOGE("RtcReadWriteMinTime failed"); return -1; } @@ -225,7 +225,7 @@ static int32_t RtcReadWriteAlarmTime(void) tm.weekday = weekday; ret = RtcReadWriteAlarmTimeTest(&tm); if (ret != 0) { - HDF_LOGE("RtcReadWriteAlarmTime read fail"); + HDF_LOGE("RtcReadWriteAlarmTime read failed"); return -1; } @@ -249,7 +249,7 @@ static int32_t RtcReadWriteMaxAlarmTime(void) tm.weekday = weekday; ret = RtcReadWriteAlarmTimeTest(&tm); if (ret == 0) { - HDF_LOGE("RtcReadWriteMaxAlarmTime read fail"); + HDF_LOGE("RtcReadWriteMaxAlarmTime read failed"); return -1; } @@ -273,7 +273,7 @@ static int32_t RtcReadWriteMinAlarmTime(void) time.weekday = weekday; ret = RtcReadWriteAlarmTimeTest(&time); if (ret == 0) { - HDF_LOGE("RtcReadWriteMinAlarmTime read fail"); + HDF_LOGE("RtcReadWriteMinAlarmTime read failed"); return -1; } @@ -299,12 +299,12 @@ static int32_t RtcAlarmEnable(void) tm.weekday = weekday; ret = RtcReadWriteAlarmTimeTest(&tm); if (ret != 0) { - HDF_LOGE("RtcReadWriteAlarmTime read fail"); + HDF_LOGE("RtcReadWriteAlarmTime read failed"); return -1; } ret = RtcAlarmInterruptEnable(g_rtcHandle, RTC_ALARM_INDEX_A, 1); if (ret != 0) { - HDF_LOGE("RtcAlarmInterruptEnable fail"); + HDF_LOGE("RtcAlarmInterruptEnable failed"); return -1; } return 0; @@ -323,17 +323,17 @@ static int32_t RtcAlarmIrqAttachConfig(void) ret = RtcRegisterAlarmCallback(g_rtcHandle, RTC_ALARM_INDEX_A, RtcAlarmACallback); if (ret != 0) { - HDF_LOGE("RtcRegisterAlarmCallback fail"); + HDF_LOGE("RtcRegisterAlarmCallback failed"); return -1; } ret = RtcSetFreq(g_rtcHandle, freq); if (ret != 0) { - HDF_LOGE("RtcSetFreq fail"); + HDF_LOGE("RtcSetFreq failed"); return -1; } ret = RtcAlarmInterruptEnable(g_rtcHandle, RTC_ALARM_INDEX_A, 1); if (ret != 0) { - HDF_LOGE("RtcAlarmInterruptEnable fail"); + HDF_LOGE("RtcAlarmInterruptEnable failed"); return -1; } return 0; @@ -361,24 +361,24 @@ static int32_t RtcAlarmIrq(void) time.weekday = weekday; ret = RtcAlarmIrqAttachConfig(); if (ret != 0) { - HDF_LOGE("RtcWriteTime fail"); + HDF_LOGE("RtcWriteTime failed"); return -1; } ret = RtcWriteTime(g_rtcHandle, &time); if (ret != 0) { - HDF_LOGE("RtcWriteTime fail"); + HDF_LOGE("RtcWriteTime failed"); return -1; } /* set alarm time 2020-08-08 Saturday 08:08:09 .000 */ time.second = RTC_TEST_TIME_SECOND + 1; ret = RtcWriteAlarm(g_rtcHandle, RTC_ALARM_INDEX_A, &time); if (ret != 0) { - HDF_LOGE("RtcWriteAlarm fail"); + HDF_LOGE("RtcWriteAlarm failed"); return -1; } OsalSleep(RTC_TEST_WAIT_TIME_S); if (g_rtcIrqCallback == HDF_FAILURE) { - HDF_LOGE("RtcWriteAlarm fail"); + HDF_LOGE("RtcWriteAlarm failed"); return -1; } g_rtcIrqCallback = HDF_FAILURE; @@ -394,7 +394,7 @@ static int32_t RtcRegisterCallback(void) } ret = RtcRegisterAlarmCallback(g_rtcHandle, RTC_ALARM_INDEX_A, RtcAlarmACallback); if (ret != 0) { - HDF_LOGE("RtcRegisterCallback fail"); + HDF_LOGE("RtcRegisterCallback failed"); return -1; } return 0; @@ -410,7 +410,7 @@ static int32_t RtcRegisterNullCallback(void) ret = RtcRegisterAlarmCallback(g_rtcHandle, RTC_ALARM_INDEX_A, NULL); if (ret == 0) { - HDF_LOGE("RtcRegisterCallback fail"); + HDF_LOGE("RtcRegisterCallback failed"); return -1; } return 0; @@ -426,7 +426,7 @@ static int32_t RtcSetNormalFreq(void) ret = RtcSetFreq(g_rtcHandle, RTC_TEST_FREQ); if (ret != 0) { - HDF_LOGE("RtcSetNormalFreq fail"); + HDF_LOGE("RtcSetNormalFreq failed"); return -1; } return 0; @@ -442,7 +442,7 @@ static int32_t RtcSetMaxFreq(void) ret = RtcSetFreq(g_rtcHandle, RTC_TEST_FREQ * RTC_TIME_UNIT); if (ret == 0) { - HDF_LOGE("RtcSetMaxFreq fail"); + HDF_LOGE("RtcSetMaxFreq failed"); return -1; } return 0; @@ -458,7 +458,7 @@ static int32_t RtcSetMinFreq(void) ret = RtcSetFreq(g_rtcHandle, 0); if (ret == 0) { - HDF_LOGE("RtcSetMinFreq fail"); + HDF_LOGE("RtcSetMinFreq failed"); return -1; } ret = RtcSetFreq(g_rtcHandle, RTC_TEST_FREQ); @@ -476,12 +476,12 @@ static int32_t RtcReadWriteUserReg(void) ret = RtcWriteReg(g_rtcHandle, 0, value); if (ret != 0) { - HDF_LOGE("RtcReadWriteUserReg write fail"); + HDF_LOGE("RtcReadWriteUserReg write failed"); return -1; } ret = RtcReadReg(g_rtcHandle, 0, &value); if (ret != 0) { - HDF_LOGE("RtcSetMinFreq read fail"); + HDF_LOGE("RtcSetMinFreq read failed"); return -1; } if (value != RTC_TEST_USER_VALUE) { @@ -501,12 +501,12 @@ static int32_t RtcReadWriteMaxUserIndex(void) ret = RtcWriteReg(g_rtcHandle, RTC_TEST_USER_MAX_INDEX, value); if (ret == 0) { - HDF_LOGE("RtcReadWriteUserReg write fail"); + HDF_LOGE("RtcReadWriteUserReg write failed"); return -1; } ret = RtcReadReg(g_rtcHandle, RTC_TEST_USER_MAX_INDEX, &value); if (ret == 0) { - HDF_LOGE("RtcSetMinFreq read fail"); + HDF_LOGE("RtcSetMinFreq read failed"); return -1; } return 0; diff --git a/test/unittest/platform/hdf_rtc_entry_test.h b/test/unittest/platform/hdf_rtc_entry_test.h index 98df0ef6..3f3997e1 100644 --- a/test/unittest/platform/hdf_rtc_entry_test.h +++ b/test/unittest/platform/hdf_rtc_entry_test.h @@ -34,4 +34,4 @@ typedef enum { } HdfRtcTestCaseCmd; int32_t HdfRtcEntry(HdfTestMsg *msg); -#endif // HDF_RTC_ENTRY_TEST_H \ No newline at end of file +#endif /* HDF_RTC_ENTRY_TEST_H */ diff --git a/test/unittest/sensor/hdf_sensor_test.c b/test/unittest/sensor/hdf_sensor_test.c index 45526d45..09f5485d 100644 --- a/test/unittest/sensor/hdf_sensor_test.c +++ b/test/unittest/sensor/hdf_sensor_test.c @@ -177,7 +177,7 @@ int32_t InitSensorDriverTest(struct HdfDeviceObject *device) struct SensorDeviceInfo deviceInfo = { .sensorInfo = { .sensorName = "sensor_test", - .vendorName = "huawei", + .vendorName = "default", .firmwareVersion = "1.0", .hardwareVersion = "1.0", .sensorTypeId = SENSOR_TAG_NONE, diff --git a/test/unittest/wifi/hdf_wifi_test.c b/test/unittest/wifi/hdf_wifi_test.c index 30f5053b..4132c8fa 100644 --- a/test/unittest/wifi/hdf_wifi_test.c +++ b/test/unittest/wifi/hdf_wifi_test.c @@ -54,10 +54,15 @@ int32_t HdfWifiEntry(HdfTestMsg *msg) { int32_t result, i; + if (msg == NULL) { + HDF_LOGE("%s is fail: HdfTestMsg is NULL!", __func__); + return HDF_SUCCESS; + } + for (i = 0; i < sizeof(g_hdfWiFiTestCaseList) / sizeof(g_hdfWiFiTestCaseList[0]); ++i) { if ((msg->subCmd == g_hdfWiFiTestCaseList[i].subCmd) && (g_hdfWiFiTestCaseList[i].testFunc != NULL)) { result = g_hdfWiFiTestCaseList[i].testFunc(); - HDF_LOGE("HdfTest:Wifi test result[%s-%d]", ((result == 0) ? "pass" : "fail"), msg->subCmd); + HDF_LOGE("HdfTest:Wifi test result[%s-%u]", ((result == 0) ? "pass" : "fail"), msg->subCmd); msg->result = (result == 0) ? HDF_SUCCESS : HDF_FAILURE; return HDF_SUCCESS; } diff --git a/test/unittest/wifi/hdf_wifi_test.h b/test/unittest/wifi/hdf_wifi_test.h index 3cf27f56..294ecec4 100644 --- a/test/unittest/wifi/hdf_wifi_test.h +++ b/test/unittest/wifi/hdf_wifi_test.h @@ -44,7 +44,6 @@ typedef enum { WIFI_MODULE_ADD_FEATURE, WIFI_MODULE_DELETE_FEATURE, WIFI_MODULE_END = 200, - /* message */ WIFI_MESSAGE_QUEUE_001 = WIFI_MODULE_END, WIFI_MESSAGE_QUEUE_002, diff --git a/tools/hc-gen/Makefile b/tools/hc-gen/Makefile index 3b75b8ee..9dcdfae0 100644 --- a/tools/hc-gen/Makefile +++ b/tools/hc-gen/Makefile @@ -16,7 +16,7 @@ BOUNDS_CHECK_LIB := $(abspath ../../../../third_party/bounds_checking_function/) INCLUDE_DIR := ./include $(BOUNDS_CHECK_LIB)/include OUT_DIR := build -TEST_CASE := $(abspath ../../../adapter/khdf/liteos/test/tools/hc-gen/test/unittest) +TEST_CASE := $(abspath ../../../adapter/lite/khdf/test/tools/hc-gen/test/unittest) ORIGIN_SOURCES := $(wildcard src/*) ORIGIN_SOURCES += $(wildcard $(BOUNDS_CHECK_LIB)/src/*) diff --git a/tools/hc-gen/README.md b/tools/hc-gen/README.md index 7a56a9e8..40a65171 100755 --- a/tools/hc-gen/README.md +++ b/tools/hc-gen/README.md @@ -1 +1 @@ -hc-gen compilation requires flex and bison, make sure that they are installed before compiling. +hc-gen compilation requires flex and bison, so make sure they are installed before you get start. \ No newline at end of file diff --git a/tools/hc-gen/bin/hc-gen b/tools/hc-gen/bin/hc-gen index 196de1293733a24442bb4937cf670066b108a76a..a759c47705c7acf92e7cc4111cd42104253c7546 100755 GIT binary patch literal 80360 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 N>Hp4&bcDCj{~vd%TnzvK literal 92808 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 -int32_t HcsBytecodeOutput(); -int32_t HcsTextCodeOutput(); +int32_t HcsBytecodeOutput(void); +int32_t HcsTextCodeOutput(void); int32_t HcsBinaryToHexdump(const char *inputFileName); #endif // HCS_COMPILER_GENER_H diff --git a/tools/hc-gen/include/hcs_log.h b/tools/hc-gen/include/hcs_log.h index bc71064a..76b8ff80 100644 --- a/tools/hc-gen/include/hcs_log.h +++ b/tools/hc-gen/include/hcs_log.h @@ -39,7 +39,7 @@ #define HCS_OBJECT_PR(prefix, object, fmt, args...) \ do { \ - HCS_LOG_PRINT (prefix": %s:%u\n\t" fmt"\n", \ + HCS_LOG_PRINT(prefix": %s:%u\n\t" fmt"\n", \ object ? ((ParserObjectBase*)object)->src : "unknown", \ object ? ((ParserObjectBase*)object)->lineno : 0, \ ##args); \ @@ -52,12 +52,20 @@ #define PRINTF_CHECK_AND_RETURN(printRes) \ do { \ if ((printRes) < 0) { \ - HCS_ERROR("Error:%s(%d), sprintf_s fail", \ + HCS_ERROR("Error:%s(%d), sprintf_s failed", \ + __FUNCTION__, __LINE__); \ + return EOUTPUT; \ + } \ + } while (0) + +#define OUTPUT_CHECK_AND_RETURN(printRes) \ + do { \ + if ((printRes) < 0) { \ + HCS_ERROR("Error:%s(%d), output write failed", \ __FUNCTION__, __LINE__); \ return EOUTPUT; \ } \ } while (0) -#define SPRINTF_ERROR_INFO "sprintf fail" #endif // HCS_COMPILER_LOG_H diff --git a/tools/hc-gen/include/hcs_opcode.h b/tools/hc-gen/include/hcs_opcode.h index 0c32eacb..1e8f1d65 100644 --- a/tools/hc-gen/include/hcs_opcode.h +++ b/tools/hc-gen/include/hcs_opcode.h @@ -27,7 +27,7 @@ typedef struct { const char *opStr; } OpCodeMapEntry; -const OpCodeMapEntry *HcsGetOpCodeMap(); +const OpCodeMapEntry *HcsGetOpCodeMap(void); const OpCodeMapEntry *HcsParserObjectTypeToByteCode(uint32_t objectType); diff --git a/tools/hc-gen/include/hcs_option.h b/tools/hc-gen/include/hcs_option.h index 034d940c..9ec430e7 100644 --- a/tools/hc-gen/include/hcs_option.h +++ b/tools/hc-gen/include/hcs_option.h @@ -10,20 +10,20 @@ #define HCS_COMPILER_OPTION_H #include -bool HcsOptShouldAlign(); +bool HcsOptShouldAlign(void); void HcsOptSetAlign(bool align); -bool HcsOptShouldGenTextConfig(); +bool HcsOptShouldGenTextConfig(void); -bool HcsOptShouldGenByteCodeConfig(); +bool HcsOptShouldGenByteCodeConfig(void); -bool HcsOptDecompile(); +bool HcsOptDecompile(void); -bool HcsOptShouldGenHexdump(); +bool HcsOptShouldGenHexdump(void); -const char *HcsOptGetSymbolNamePrefix(); +const char *HcsOptGetSymbolNamePrefix(void); -bool HcsVerbosePrint(); +bool HcsVerbosePrint(void); #endif // HCS_COMPILER_OPTION_H diff --git a/tools/hc-gen/src/hcs_ast.c b/tools/hc-gen/src/hcs_ast.c index 5b2365f4..4348483a 100644 --- a/tools/hc-gen/src/hcs_ast.c +++ b/tools/hc-gen/src/hcs_ast.c @@ -6,13 +6,13 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "hcs_ast.h" #include #include #include "hcs_file.h" #include "hcs_mem.h" #include "hcs_log.h" #include "hcs_option.h" -#include "hcs_ast.h" #define ANONYMOUS_OBJECT_NAME "|_" static ParserObject *g_parserRoot = NULL; @@ -24,14 +24,14 @@ bool HcsIsAnonymousObject(const ParserObject *obj) ParserObject *HcsAllocParserObject(void) { - ParserObject *new = (ParserObject *)HcsMemZalloc(sizeof(ParserObject)); - if (new == NULL) { - HCS_ERROR("%s %d %s OOM", __FILE__, __LINE__, __func__); + ParserObject *newObject = (ParserObject *)HcsMemZalloc(sizeof(ParserObject)); + if (newObject == NULL) { + HCS_ERROR("%s:%d OOM", __func__, __LINE__); return NULL; } - new->objectBase.src = HcsGetCurrentSourceName(); - new->objectBase.lineno = HcsGetCurrentSourceLine(); - return new; + newObject->objectBase.src = HcsGetCurrentSourceName(); + newObject->objectBase.lineno = HcsGetCurrentSourceLine(); + return newObject; } void HcsAstFreeObject(ParserObject *object) @@ -77,7 +77,7 @@ void HcsDeleteParserObjectTree(ParserObject *object) if (object == NULL) { return; } - /* delete current and subtree */ + /* delete current tree and subtree */ HcsAstFreeObjectAndSubtree(object); } @@ -89,7 +89,7 @@ ParserObject *HcsGetParserRoot(void) HCS_DEBUG("instance root node"); char *rootNodeName = strdup("root"); if (rootNodeName == NULL) { - HCS_ERROR("%s %d %s OOM", __FILE__, __LINE__, __func__); + HCS_ERROR("%s:%d OOM", __func__, __LINE__); return NULL; } g_parserRoot = HcsNewConfigNode(rootNodeName, CONFIG_NODE_NOREF, NULL); @@ -311,7 +311,7 @@ static ParserObject *HcsParserObjectClone(const ParserObject *object) } ParserObject *clone = HcsAllocParserObject(); if (clone == NULL) { - HCS_ERROR("%s %d %s OOM", __FILE__, __LINE__, __func__); + HCS_ERROR("%s:%d OOM", __func__, __LINE__); return NULL; } @@ -384,7 +384,7 @@ int32_t HcsAstCopyArray(const ParserObject *src, ParserObject *dst) while (arrayElement != NULL) { ParserObject *copy = HcsParserObjectClone(arrayElement); if (copy == NULL) { - HCS_ERROR("%s %d %s OOM", __FILE__, __LINE__, __func__); + HCS_ERROR("%s:%d OOM", __func__, __LINE__); return EOOM; } HcsAstAddChild(dst, copy); @@ -407,7 +407,7 @@ static int32_t HcsCopyObject(const ParserObject *src, ParserObject *dst) HcsMemFree(dst->objectBase.stringValue); dst->objectBase.stringValue = strdup(src->objectBase.stringValue); if (dst->objectBase.stringValue == NULL) { - HCS_ERROR("%s %d %s OOM", __FILE__, __LINE__, __func__); + HCS_ERROR("%s:%d OOM", __func__, __LINE__); return EOOM; } } else if (src->objectBase.type == PARSEROP_ARRAY) { @@ -442,7 +442,6 @@ static int32_t HcsAstCopyTree(ParserObject *src, ParserObject *dstTree, uint32_t } } else if (HcsOptShouldGenTextConfig() && HcsIsNumberObject(src) && dstExistObject->objectBase.type > src->objectBase.type) { - /* At template case, should do type upward transformation to template */ src->objectBase.type = dstExistObject->objectBase.type; } diff --git a/tools/hc-gen/src/hcs_bytecode_gen.c b/tools/hc-gen/src/hcs_bytecode_gen.c index 39512292..caf56b8b 100644 --- a/tools/hc-gen/src/hcs_bytecode_gen.c +++ b/tools/hc-gen/src/hcs_bytecode_gen.c @@ -83,9 +83,9 @@ static int32_t ByteCodeWriteWalk(ParserObject *current, int32_t walkDepth) } int32_t ret = NOERR; switch (current->objectBase.opCode) { - case HCS_BYTE_OP: - case HCS_WORD_OP: - case HCS_DWORD_OP: + case HCS_BYTE_OP: /* fall-through */ + case HCS_WORD_OP: /* fall-through */ + case HCS_DWORD_OP: /* fall-through */ case HCS_QWORD_OP: { const OpCodeMapEntry *byteCodeMap = HcsGetOpCodeMap(); ret = HcsOutputWriteAlign(¤t->objectBase.integerValue, byteCodeMap[current->objectBase.type].size); @@ -103,7 +103,6 @@ static int32_t ByteCodeWriteWalk(ParserObject *current, int32_t walkDepth) } ret = HcsOutputWriteAlign(¤t->objectBase.subSize, sizeof(current->objectBase.subSize)); break; - /* fall-through */ case HCS_ARRAY_OP: { uint16_t size = HcsCountArraySize(current); ret = HcsOutputWriteAlign(&size, sizeof(size)); @@ -122,20 +121,20 @@ static int32_t ByteCodeWriteWalk(ParserObject *current, int32_t walkDepth) return ret; } -int32_t HcsBytecodeOutput() +int32_t HcsBytecodeOutput(void) { ParserObject *astRoot = HcsGetParserRoot(); if (astRoot == NULL) { return EFAIL; } - /* generate OpCode for every object on AST and calculate size for each */ + /* generate OpCode for every object on AST and calculate size for each object */ int32_t ret = HcsWalkAst(astRoot, AST_WALK_BACKEND, NULL, ByteCodeConvert); if (ret) { return ret; } - /* ast data is ready, do binder output */ + /* ast data is ready, do bindary output */ struct HcsFile *outputFIle = HcsOpenOutputFile(HCS_OUTPUT_FILE_SUFFIX); HbcHeader header = { @@ -181,7 +180,7 @@ int32_t HcsBytecodeOutput() HcsCloseOutput(outputFIle); HCS_DEBUG("Total size: %u ", astRoot->objectBase.size); if (ret == NOERR && HcsOptShouldGenHexdump()) { - ret = HcsBinaryToHexdump(HcsGetOutPutFileName()); + ret = HcsBinaryToHexdump(HcsGetOutPutFilePath()); } return ret; } diff --git a/tools/hc-gen/src/hcs_decompile_gen.c b/tools/hc-gen/src/hcs_decompile_gen.c index 5959fc52..c253ff2b 100644 --- a/tools/hc-gen/src/hcs_decompile_gen.c +++ b/tools/hc-gen/src/hcs_decompile_gen.c @@ -30,7 +30,7 @@ static char *HcsAssembleNodeRefName(char *buff, uint32_t buffSize, const char *n } char *str = strdup(buff); if (str == NULL) { - HCS_ERROR("%s %d %s OOM", __FILE__, __LINE__, __func__); + HCS_ERROR("%s:%d OOM", __func__, __LINE__); return NULL; } return str; @@ -83,65 +83,59 @@ static char *HcsGetNodeRefPath(uint64_t hash) return NULL; } -static int32_t HcsDecompilePrintBaseType(char *buffer, uint32_t bufferSize, const ParserObject *object); +static int32_t HcsDecompilePrintBaseType(const ParserObject *object); -static int32_t HcsDecompilePrintArrayType(char *buffer, uint32_t bufferSize, const ParserObject *object) +static int32_t HcsDecompilePrintArrayType(const ParserObject *object) { - int32_t res = sprintf_s(buffer, bufferSize, "["); - PRINTF_CHECK_AND_RETURN(res); + int32_t res; + PRINTF_CHECK_AND_RETURN(HcsFormatOutputWrite("[")); ParserObject *arrayElement = (ParserObject *)object->objectBase.child; while (arrayElement->objectBase.next) { - res = HcsDecompilePrintBaseType(buffer + strlen(buffer), bufferSize - strlen(buffer), arrayElement); + res = HcsDecompilePrintBaseType(arrayElement); if (res) { return EOUTPUT; } - res = sprintf_s(buffer + strlen(buffer), bufferSize - strlen(buffer), ", "); - PRINTF_CHECK_AND_RETURN(res); + PRINTF_CHECK_AND_RETURN(HcsFormatOutputWrite(", ")); arrayElement = (ParserObject *)arrayElement->objectBase.next; } - res = HcsDecompilePrintBaseType(buffer + strlen(buffer), bufferSize - strlen(buffer), arrayElement); + res = HcsDecompilePrintBaseType(arrayElement); if (res) { return EOUTPUT; } - res = sprintf_s(buffer + strlen(buffer), bufferSize - strlen(buffer), "]"); - PRINTF_CHECK_AND_RETURN(res); - return NOERR; + return HcsFormatOutputWrite("]"); } -static int32_t HcsDecompilePrintBaseType(char *buffer, uint32_t bufferSize, const ParserObject *object) +static int32_t HcsDecompilePrintBaseType(const ParserObject *object) { - int32_t res; + int32_t res = NOERR; switch (object->objectBase.type) { case PARSEROP_UINT8: case PARSEROP_UINT16: case PARSEROP_UINT32: case PARSEROP_UINT64: - res = sprintf_s(buffer, bufferSize, "0x%"PRIx64, object->objectBase.integerValue); - PRINTF_CHECK_AND_RETURN(res); + res = HcsFormatOutputWrite("0x%"PRIx64, object->objectBase.integerValue); break; case PARSEROP_STRING: - res = sprintf_s(buffer, bufferSize, "\"%s\"", object->objectBase.stringValue); - PRINTF_CHECK_AND_RETURN(res); + res = HcsFormatOutputWrite("\"%s\"", object->objectBase.stringValue); break; case PARSEROP_NODEREF: { char *refPath = HcsGetNodeRefPath(object->objectBase.value); if (refPath == NULL) { return EOUTPUT; } - res = sprintf_s(buffer, bufferSize, "&%s", refPath); + res = HcsFormatOutputWrite("&%s", refPath); HcsMemFree(refPath); - PRINTF_CHECK_AND_RETURN(res); } break; case PARSEROP_ARRAY: - return HcsDecompilePrintArrayType(buffer, bufferSize, object); + return HcsDecompilePrintArrayType(object); default: HCS_ERROR("unknown OpCode %u", object->objectBase.type); return EFAIL; } - return NOERR; + return res; } static int32_t HcsDecompileOutputWalk(ParserObject *current, int32_t walkDepth) @@ -151,41 +145,31 @@ static int32_t HcsDecompileOutputWalk(ParserObject *current, int32_t walkDepth) } int32_t res; - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; int32_t tabSize = walkDepth * HCS_TAB_SIZE; if (walkDepth) { - res = sprintf_s(writeBuffer, WRITE_BUFFER_LEN, "%*c", tabSize, ' '); - PRINTF_CHECK_AND_RETURN(res); + PRINTF_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c", tabSize, ' ')); } switch (current->objectBase.type) { case PARSEROP_CONFNODE: - res = sprintf_s(writeBuffer + strlen(writeBuffer), WRITE_BUFFER_LEN - strlen(writeBuffer), - "%s {\n", current->configNode.name); - PRINTF_CHECK_AND_RETURN(res); + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%s {\n", current->configNode.name)); if (current->objectBase.child == NULL) { - res = sprintf_s(writeBuffer + strlen(writeBuffer) - 1, - WRITE_BUFFER_LEN - strlen(writeBuffer) + 1, "}\n"); - PRINTF_CHECK_AND_RETURN(res); + return HcsFormatOutputWrite("%*c}\n", tabSize, ' '); } break; case PARSEROP_CONFTERM: - res = sprintf_s(writeBuffer + strlen(writeBuffer), WRITE_BUFFER_LEN - strlen(writeBuffer), - "%s = ", current->configNode.name); - PRINTF_CHECK_AND_RETURN(res); - res = HcsDecompilePrintBaseType(writeBuffer + strlen(writeBuffer), WRITE_BUFFER_LEN - strlen(writeBuffer), - (ParserObject *)current->configNode.child); + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%s = ", current->configNode.name)); + res = HcsDecompilePrintBaseType( + (ParserObject *) current->configNode.child); if (res) { return res; } - res = sprintf_s(writeBuffer + strlen(writeBuffer), WRITE_BUFFER_LEN - strlen(writeBuffer), ";\n"); - PRINTF_CHECK_AND_RETURN(res); - break; + return HcsFormatOutputWrite(";\n"); default: break; } - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); + return NOERR; } static int32_t HcsDecompileCloseBraceGen(ParserObject *current, int32_t walkDepth) @@ -193,22 +177,13 @@ static int32_t HcsDecompileCloseBraceGen(ParserObject *current, int32_t walkDept if (current->objectBase.type != PARSEROP_CONFNODE) { return NOERR; } - int32_t res; int32_t tabSize = walkDepth * HCS_TAB_SIZE; - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; - if (current != HcsGetParserRoot()) { - res = sprintf_s(writeBuffer, WRITE_BUFFER_LEN, "%*c}\n", tabSize, ' '); - PRINTF_CHECK_AND_RETURN(res); - } else { - res = sprintf_s(writeBuffer, WRITE_BUFFER_LEN, "}\n"); - PRINTF_CHECK_AND_RETURN(res); - } - - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); + return current != HcsGetParserRoot() ? HcsFormatOutputWrite("%*c}\n", tabSize, ' ') : + HcsFormatOutputWrite("}\n"); } -int32_t HcsDecompileOutput() +int32_t HcsDecompileOutput(void) { ParserObject *astRoot = HcsGetParserRoot(); if (astRoot == NULL) { @@ -221,8 +196,7 @@ int32_t HcsDecompileOutput() goto OUT; } - const char *fileHeader = HCS_DECOMPILE_FILE_HEADER; - if (HcsOutputWrite(fileHeader, strlen(fileHeader))) { + if (HcsFormatOutputWrite(HCS_DECOMPILE_FILE_HEADER) != EOK) { goto OUT; } diff --git a/tools/hc-gen/src/hcs_decompiler.c b/tools/hc-gen/src/hcs_decompiler.c index 2aac4443..f69414e1 100644 --- a/tools/hc-gen/src/hcs_decompiler.c +++ b/tools/hc-gen/src/hcs_decompiler.c @@ -6,14 +6,14 @@ * See the LICENSE file in the root of this repository for complete details. */ -#include +#include "hcs_decompiler.h" +#include #include "hcs_option.h" #include "hcs_file.h" #include "hcs_opcode.h" #include "hcs_parser.h" #include "hcs_log.h" #include "hcs_compiler.h" -#include "hcs_decompiler.h" static ParserObject *RebuildObject(uint8_t opCode); @@ -42,7 +42,7 @@ static bool HcsVerifyHbcFile() } HCS_INFO("Build by hcs compile %u.%u", header.versionMajor, header.versionMinor); - HCS_INFO("hcb file total size: %u\n", header.totalSize); + HCS_INFO("hcb file total size: %d\n", header.totalSize); return true; } @@ -74,7 +74,7 @@ static char *ReadCString() } char *str = strdup(buff); if (str == NULL) { - HCS_ERROR("%s %d %s OOM", __FILE__, __LINE__, __func__); + HCS_ERROR("%s:%d OOM", __func__, __LINE__); return NULL; } return str; @@ -348,7 +348,7 @@ static bool RebuildAst() return true; } -int32_t HcsDoDecompile() +int32_t HcsDoDecompile(void) { struct HcsFile *source = NULL; uint32_t ret = HcsOpenSourceFile(HcsGetInputFileName(), &source, "rb"); diff --git a/tools/hc-gen/src/hcs_file.c b/tools/hc-gen/src/hcs_file.c index 34b50002..e3cdedaa 100644 --- a/tools/hc-gen/src/hcs_file.c +++ b/tools/hc-gen/src/hcs_file.c @@ -6,6 +6,7 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "hcs_file.h" #include #include #include @@ -15,11 +16,10 @@ #include "hcs_parser.h" #include "hcs_mem.h" #include "hcs_log.h" -#include "hcs_file.h" -static char *g_outputFilename = NULL; -static FILE *g_outputFIle = NULL; -const char *g_inputFileName = NULL; +static char *g_outputFileName = NULL; +static FILE *g_outputFile = NULL; +static const char *g_inputFileName = NULL; static bool g_dummyOutput = false; static uint32_t g_outputWriteCount = 0; static struct HcsFileQueue g_inputSourceFileQueue = { 0 }; @@ -30,20 +30,17 @@ void HcsSetInputFileName(const char *name) g_inputFileName = name; } -const char *HcsGetInputFileName() +const char *HcsGetInputFileName(void) { return g_inputFileName; } -/* - * Return: true - not exist, false - already exist and not overwrite - */ int32_t HcsSourceNameSetPush(const char *name) { if (g_sourceNameSetHead == NULL) { struct HcsSourceName *head = HcsMemZalloc(sizeof(*head)); if (head == NULL) { - HCS_ERROR("%s %d %s OOM", __FILE__, __LINE__, __func__); + HCS_ERROR("%s:%d OOM", __func__, __LINE__); return EOOM; } head->name = name; @@ -61,13 +58,13 @@ int32_t HcsSourceNameSetPush(const char *name) last = last->next; } - struct HcsSourceName *new = HcsMemZalloc(sizeof(struct HcsSourceName)); - if (new == NULL) { - HCS_ERROR("%s %d %s OOM", __FILE__, __LINE__, __func__); + struct HcsSourceName *newName = HcsMemZalloc(sizeof(struct HcsSourceName)); + if (newName == NULL) { + HCS_ERROR("%s:%d OOM", __func__, __LINE__); return EOOM; } - new->name = name; - pre->next = new; + newName->name = name; + pre->next = newName; return NOERR; } @@ -101,6 +98,9 @@ void HcsSourceNameSetClean(void) static const char *GetFileName(const char *path) { + if (path == NULL) { + return NULL; + } int32_t length = (int32_t)strlen(path); int32_t i = length - 1; for (; i >= 0; --i) { @@ -147,7 +147,7 @@ static int32_t CopyAndSaveFileName(const char *filePath, char **savedFileName, c } /* if no specified output file name, use input name */ - if (HcsGetOutPutFileName() == NULL && HcsSetOutPutNameWithCurrentWorkPath(fileName)) { + if (HcsGetOutPutFilePath() == NULL && HcsSetOutPutNameWithCurrentWorkPath(fileName)) { HcsMemFree((void *)fileName); return EOOM; } @@ -172,26 +172,25 @@ int32_t HcsOpenSourceFile(const char *path, struct HcsFile **file, const char *f char *realPath = realpath(path, pathBuf); #endif if (realPath == NULL) { - HCS_ERROR("fail to open source file: %s", path); + HCS_ERROR("failed to open source file: %s", path); return EINVALF; } /* push to name set and check reopen */ - int32_t ret = HcsSourceNameSetFind(realPath); - if (ret == true) { + if (HcsSourceNameSetFind(realPath)) { return EREOPENF; } HCS_DEBUG("source file path: %s", realPath); FILE *f = fopen(realPath, flag ? flag : "r"); if (f == NULL) { - HCS_ERROR("fail to open source file: %s", realPath); + HCS_ERROR("failed to open source file: %s", realPath); return EINVALF; } char *fileName = NULL; char *filePath = NULL; - ret = CopyAndSaveFileName(realPath, &fileName, &filePath); + int32_t ret = CopyAndSaveFileName(realPath, &fileName, &filePath); if (ret) { fclose(f); return EFAIL; @@ -200,6 +199,7 @@ int32_t HcsOpenSourceFile(const char *path, struct HcsFile **file, const char *f struct HcsFile *sourceFile = HcsMemZalloc(sizeof(struct HcsFile)); if (sourceFile == NULL) { HcsMemFree(fileName); + HcsMemFree(filePath); fclose(f); HCS_ERROR("oom"); return EOOM; @@ -272,17 +272,17 @@ int32_t HcsSetOutPutNameWithCurrentWorkPath(const char *name) int32_t HcsSetOutPutName(const char *name) { - if (g_outputFilename != NULL) { - HcsMemFree(g_outputFilename); + if (g_outputFileName != NULL) { + HcsMemFree(g_outputFileName); } - g_outputFilename = strdup(name); - if (g_outputFilename == NULL) { + g_outputFileName = strdup(name); + if (g_outputFileName == NULL) { HCS_ERROR("oom"); return EOOM; } #ifdef OS_WIN - char *temp = g_outputFilename; + char *temp = g_outputFileName; while (*temp != '\0') { if (*temp == UNIX_SEPARATOR) { *temp = WIN_SEPARATOR; @@ -296,13 +296,13 @@ int32_t HcsSetOutPutName(const char *name) bool HcsSetOutputFileSuffix(const char *suffix) { - const char *fileNameBefore = g_outputFilename; + const char *fileNameBefore = g_outputFileName; const char *fileNameWithoutSuffix = GetFileNameWithoutSuffix(fileNameBefore); if (fileNameWithoutSuffix == NULL) { return false; } - uint32_t newNameSize = strlen(g_outputFilename) + strlen(suffix) + 1; + uint32_t newNameSize = strlen(g_outputFileName) + strlen(suffix) + 1; char *newOutputFilename = HcsMemZalloc(newNameSize); if (newOutputFilename == NULL) { HcsMemFree((void *)fileNameWithoutSuffix); @@ -312,37 +312,58 @@ bool HcsSetOutputFileSuffix(const char *suffix) int32_t ret = strcpy_s(newOutputFilename, newNameSize, fileNameWithoutSuffix); HcsMemFree((void *)fileNameWithoutSuffix); if (ret) { - HCS_ERROR("string copy fail"); + HCS_ERROR("failed to copy string"); HcsMemFree(newOutputFilename); return false; } ret = strcat_s(newOutputFilename, newNameSize, suffix); if (ret) { - HCS_ERROR("string copy fail"); + HCS_ERROR("failed to copy string"); HcsMemFree(newOutputFilename); return false; } HcsMemFree((void *)fileNameBefore); - g_outputFilename = newOutputFilename; + g_outputFileName = newOutputFilename; return true; } // return output file name only -const char *HcsGetStripedOutputFileName() +const char *HcsGetOutputFileName(void) { - return GetFileName(g_outputFilename); + return GetFileName(g_outputFileName); } -// return full path of output file -const char *HcsGetOutPutFileName() +char *HcsGetOutputFileNameWithoutSuffix(void) { - return g_outputFilename; + const char *fileName = HcsGetOutputFileName(); + if (fileName == NULL) { + return NULL; + } + + char *retName = strdup(fileName); + if (retName == NULL) { + HCS_ERROR("oom"); + return NULL; + } + + char *dot = strchr(retName, '.'); + if (dot != NULL) { + *dot = '\0'; + } + return retName; +} + + +// return full path of output file +const char *HcsGetOutPutFilePath(void) +{ + return g_outputFileName; } bool HcsOutputNameVerify() { - const char *fileName = g_outputFilename; + const char *fileName = g_outputFileName; char lastChar = fileName[strlen(fileName) - 1]; if (lastChar == OS_SEPARATOR) { HCS_ERROR("output name is DIR"); @@ -360,10 +381,10 @@ struct HcsFile *HcsOpenOutputFile(const char *suffix) if (!HcsSetOutputFileSuffix(suffix)) { return NULL; } - const char *outputFileName = HcsGetOutPutFileName(); - g_outputFIle = fopen(outputFileName, "wb"); - if (g_outputFIle == NULL) { - HCS_ERROR("fail to open output file: %s", outputFileName); + const char *outputFileName = HcsGetOutPutFilePath(); + g_outputFile = fopen(outputFileName, "wb"); + if (g_outputFile == NULL) { + HCS_ERROR("failed to open output file: %s", outputFileName); return NULL; } @@ -371,12 +392,12 @@ struct HcsFile *HcsOpenOutputFile(const char *suffix) struct HcsFile *outputFile = HcsMemZalloc(sizeof(struct HcsFile)); if (outputFile == NULL) { HCS_ERROR("oom"); - fclose(g_outputFIle); - g_outputFIle = NULL; + fclose(g_outputFile); + g_outputFile = NULL; return NULL; } outputFile->name = outputFileName; - outputFile->file = g_outputFIle; + outputFile->file = g_outputFile; outputFile->pos = 0; outputFile->fullPath = outputFileName; g_outputWriteCount = 0; @@ -404,15 +425,38 @@ int32_t HcsOutputWrite(const void *buffer, uint32_t length) return NOERR; } - uint32_t writeLen = fwrite(buffer, 1, length, g_outputFIle); + uint32_t writeLen = fwrite(buffer, 1, length, g_outputFile); if (writeLen != length) { - HCS_ERROR("output file write fail"); + HCS_ERROR("failed to write output file"); return EOUTPUT; } return NOERR; } +#define WRITE_MAX_PER_TIME 2048 + +int32_t HcsFormatOutputWrite(const char *format, ...) +{ + if (format == NULL) { + return EINVALARG; + } + static char writeBuffer[WRITE_MAX_PER_TIME] = {'\0'}; + + va_list argList; + + va_start(argList, format); + int length = vsprintf_s(writeBuffer, WRITE_MAX_PER_TIME, format, argList); + va_end(argList); + (void)argList; + + if (length < 0) { + HCS_ERROR("Output too long in one time"); + return EOUTPUT; + } + return HcsOutputWrite(writeBuffer, length); +} + int32_t HcsOutputWriteAlign(const void *buffer, uint32_t length) { static const uint8_t alignData[ALIGN_SIZE] = {0}; @@ -460,7 +504,7 @@ void HcsSourceQueuePush(struct HcsFile *sourceFile) sourceQueue->count++; } -void HcsSourceQueuePop() +void HcsSourceQueuePop(void) { struct HcsFileQueue *sourceQueue = &g_inputSourceFileQueue; if (sourceQueue->head == NULL) { @@ -470,17 +514,17 @@ void HcsSourceQueuePop() sourceQueue->count--; } -struct HcsFile *HcsSourceQueueTop() +struct HcsFile *HcsSourceQueueTop(void) { return g_inputSourceFileQueue.head; } -uint32_t HcsSourceQueueSize() +uint32_t HcsSourceQueueSize(void) { return g_inputSourceFileQueue.count; } -const char *HcsGetCurrentSourceName() +const char *HcsGetCurrentSourceName(void) { struct HcsFile *source = HcsSourceQueueTop(); return source ? source->fullPath : ""; @@ -488,19 +532,12 @@ const char *HcsGetCurrentSourceName() bool HcsFileCopyDir(char *dst, uint32_t dstBufferSize, const char *fullPath) { - const char *c = strlen(fullPath) + fullPath; - while (c >= fullPath) { - if (*c == OS_SEPARATOR) { - break; - } - c--; - } - int32_t len = (int32_t)(c - fullPath) + 1; - if (len <= 0) { + const char *c = strrchr(fullPath, OS_SEPARATOR); + if (c == NULL) { HCS_ERROR("%s: path '%s' not include dir", __func__, fullPath); return false; } - + int32_t len = (int32_t)(c - fullPath) + 1; int32_t ret = strncpy_s(dst, dstBufferSize, fullPath, len); if (ret) { HCS_ERROR("%s:string copy fail", __func__); diff --git a/tools/hc-gen/src/hcs_hexdump.c b/tools/hc-gen/src/hcs_hexdump.c index 59d634a5..6ac7f981 100644 --- a/tools/hc-gen/src/hcs_hexdump.c +++ b/tools/hc-gen/src/hcs_hexdump.c @@ -61,13 +61,14 @@ int32_t HcsBinaryToHexdump(const char *inputFileName) struct HcsFile *out = HcsOpenOutputFile(HCS_HEXDUMP_FILE_SUFFIX); if (out == NULL) { - HCS_ERROR("can not open %s", HcsGetOutPutFileName()); + HCS_ERROR("can not open %s", HcsGetOutPutFilePath()); + HcsCloseFile(source); return EINVALF; } int32_t ret = HcsHexdumpOutput(source->file, out->file); if (ret) { - HCS_ERROR("fail to gen bytecode hexdump in C style"); + HCS_ERROR("failed to gen bytecode hexdump in C style"); } HcsCloseFile(source); HcsCloseFile(out); diff --git a/tools/hc-gen/src/hcs_mem.c b/tools/hc-gen/src/hcs_mem.c index 410c66a2..e5ec7cb8 100644 --- a/tools/hc-gen/src/hcs_mem.c +++ b/tools/hc-gen/src/hcs_mem.c @@ -6,11 +6,11 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "hcs_mem.h" #include #include #include -#include "hcs_mem.h" -#define MEM_MAX (1024*1024) +#define MEM_MAX (1024 * 1024) void *HcsMemAlloc(uint32_t size) { @@ -18,8 +18,7 @@ void *HcsMemAlloc(uint32_t size) return NULL; } - void *newMem = malloc(size); - return newMem; + return malloc(size); } void *HcsMemZalloc(uint32_t size) diff --git a/tools/hc-gen/src/hcs_middle.c b/tools/hc-gen/src/hcs_middle.c index 35301f84..b281764d 100644 --- a/tools/hc-gen/src/hcs_middle.c +++ b/tools/hc-gen/src/hcs_middle.c @@ -38,17 +38,14 @@ static ParserObject *HcsLookupAstObject(const ParserObject *current, const char ParserObject *object = HcsGetParserRoot(); while (nodeName != NULL) { object = HcsAstLookupObjectInChildren(object, nodeName); - if (object == NULL) + if (object == NULL) { break; + } nodeName = strtok(NULL, "."); } HcsMemFree(splitPath); - if (object != NULL) { - return object; - } - - return NULL; + return object; } static int32_t HcsExpandNodeRef(ParserObject *object) @@ -105,7 +102,7 @@ static int32_t HcsExpandNodeCopy(ParserObject *object) ParserObjectBase *copyChild = copyNode->objectBase.child; while (copyChild != NULL) { if (copyChild->type == PARSEROP_CONFNODE) { - HCS_OBJECT_ERROR(object, "Not allow copy node has child node when output text config, at %s:%d", + HCS_OBJECT_ERROR(object, "Not allow copy node has child node when output text config, at %s:%u", copyChild->src, copyChild->lineno); return EINVALARG; } @@ -340,12 +337,12 @@ static bool HcsApplyDelete(ParserObject *dst, ParserObject *src) static int32_t HcsMergeTree(ParserObject *dst, ParserObject *src) { if (strcmp(src->objectBase.name, dst->objectBase.name) != 0) { - HCS_OBJECT_ERROR(src, "merge different node to %s:%d", dst->objectBase.src, dst->objectBase.lineno); + HCS_OBJECT_ERROR(src, "merge different node to %s:%u", dst->objectBase.src, dst->objectBase.lineno); return EINVALARG; } if (src->objectBase.type != dst->objectBase.type) { - HCS_OBJECT_ERROR(src, "conflict type with %s:%d", dst->objectBase.src, dst->objectBase.lineno); + HCS_OBJECT_ERROR(src, "conflict type with %s:%u", dst->objectBase.src, dst->objectBase.lineno); return EINVALARG; } @@ -373,7 +370,7 @@ static int32_t HcsMergeTree(ParserObject *dst, ParserObject *src) ParserObject *childSrcNext = (ParserObject *)childSrc->objectBase.next; ParserObject *childDst = HcsAstLookupObjectInChildren(dst, childSrc->objectBase.name); if (childDst != NULL && childSrc->objectBase.type != childDst->objectBase.type) { - HCS_OBJECT_ERROR(childSrc, "overwrite with different type at %s:%d", childDst->objectBase.src, + HCS_OBJECT_ERROR(childSrc, "overwrite with different type at %s:%u", childDst->objectBase.src, childDst->objectBase.lineno); return EINVALARG; } @@ -435,7 +432,7 @@ static int32_t HcsMiddleMerge(ParserObject **mergedRoot) return NOERR; } -int32_t HcsDoOptimize() +int32_t HcsDoOptimize(void) { ParserObject *root = HcsGetParserRoot(); if (root == NULL) { diff --git a/tools/hc-gen/src/hcs_opcode.c b/tools/hc-gen/src/hcs_opcode.c index 3bfac2df..22adaa65 100644 --- a/tools/hc-gen/src/hcs_opcode.c +++ b/tools/hc-gen/src/hcs_opcode.c @@ -6,8 +6,8 @@ * See the LICENSE file in the root of this repository for complete details. */ -#include #include "hcs_opcode.h" +#include OpCodeMapEntry g_byteCodeMap[PARSEROP_COUNT] = { @@ -22,7 +22,7 @@ OpCodeMapEntry g_byteCodeMap[PARSEROP_COUNT] = { [PARSEROP_NODEREF] = {HCS_NODEREF_OP, DWORD_SIZE, "NodeRef"}, /* RefHashCode - DWORD */ }; -const OpCodeMapEntry *HcsGetOpCodeMap() +const OpCodeMapEntry *HcsGetOpCodeMap(void) { return g_byteCodeMap; } diff --git a/tools/hc-gen/src/hcs_option.c b/tools/hc-gen/src/hcs_option.c index 3958660b..3442275e 100644 --- a/tools/hc-gen/src/hcs_option.c +++ b/tools/hc-gen/src/hcs_option.c @@ -14,15 +14,15 @@ #define ARG_COUNT_MIN 2 #define USAGE(option, info) HCS_PRINT(" %-12s%s\n", option, info) -bool g_genTextConfigOutput = false; -bool g_genByteCodeConfigOutput = true; -bool g_genByteCodeHexdump = false; -bool g_verbosePrint = false; -bool g_decompile = false; -bool g_shouldAlign = false; -const char *g_symbolPrefix = NULL; +static bool g_genTextConfigOutput = false; +static bool g_genByteCodeConfigOutput = true; +static bool g_genByteCodeHexdump = false; +static bool g_verbosePrint = false; +static bool g_decompile = false; +static bool g_shouldAlign = false; +static const char *g_symbolPrefix = NULL; -bool HcsOptShouldAlign() +bool HcsOptShouldAlign(void) { return g_shouldAlign; } @@ -32,26 +32,27 @@ void HcsOptSetAlign(bool align) g_shouldAlign = align; } - -bool HcsOptShouldGenTextConfig() +bool HcsOptShouldGenTextConfig(void) { return g_genTextConfigOutput; } -bool HcsOptShouldGenByteCodeConfig() + +bool HcsOptShouldGenByteCodeConfig(void) { return g_genByteCodeConfigOutput; } -bool HcsOptDecompile() + +bool HcsOptDecompile(void) { return g_decompile; } -const char *HcsOptGetSymbolNamePrefix() +const char *HcsOptGetSymbolNamePrefix(void) { return g_symbolPrefix; } -bool HcsOptShouldGenHexdump() +bool HcsOptShouldGenHexdump(void) { return g_genByteCodeHexdump; } @@ -151,7 +152,7 @@ int32_t DoOption(int32_t argc, char *argv[]) return 0; } -bool HcsVerbosePrint() +bool HcsVerbosePrint(void) { return g_verbosePrint; } diff --git a/tools/hc-gen/src/hcs_parser.c b/tools/hc-gen/src/hcs_parser.c index 7e595cef..40eb343f 100644 --- a/tools/hc-gen/src/hcs_parser.c +++ b/tools/hc-gen/src/hcs_parser.c @@ -125,7 +125,7 @@ int32_t HcsProcessInclude(char *includePath, uint32_t lineNumber) return NOERR; } -int32_t HcsDoCompile() +int32_t HcsDoCompile(void) { struct HcsFile *source = NULL; char *forestName = strdup("ForestRoot"); diff --git a/tools/hc-gen/src/hcs_text_gen.c b/tools/hc-gen/src/hcs_text_gen.c index 00cce070..9513c372 100644 --- a/tools/hc-gen/src/hcs_text_gen.c +++ b/tools/hc-gen/src/hcs_text_gen.c @@ -18,20 +18,16 @@ #define TAB_SIZE 4 #define WRITE_BUFFER_LEN 256 -#define INCLUDE_PATH_MAX_LEN 128 #define VARIABLE_NAME_LEN 128 -#define GEN_CODE_MARGIN_SIZE 100 -#define GEN_ARRAY_SEP_SIZE 2 +#define ELEMENT_PER_LINE 16 #define HCS_CONFIG_FILE_HEADER "/*\n" \ - " * It's HDF config auto-gen file, do not modify it manually\n" \ + " * This is an automatically generated HDF config file. Do not modify it manually.\n" \ " */\n\n" #define HCS_CONFIG_INCLUDE_HEADER "#include \n\n" #define DEFAULT_PREFIX "HdfConfig" -#define HCS_CONFIG_INCLUDE_FUNC_DECLARATION "const struct %s%sRoot* HdfGet%sModuleConfigRoot(void);\n\n" - #define HCS_CONFIG_FUNC_IMPLEMENT "\nconst struct %s%sRoot* HdfGet%sModuleConfigRoot(void)\n" \ "{\n" \ " return &%s;\n" \ @@ -96,7 +92,7 @@ static int32_t InitConfigVariableNames() return EOOM; } if (strcpy_s(g_bigHumpModuleName, strlen(moduleName) + 1, moduleName) != EOK) { - HCS_ERROR("string copy fail"); + HCS_ERROR("failed to copy string"); return EFAIL; } ToUpperCamelString(g_bigHumpModuleName, strlen(g_bigHumpModuleName)); @@ -309,14 +305,16 @@ const char *g_typeMap[PARSEROP_COUNT] = { static int32_t GenConfigStructName(const ParserObject *node, char *name, uint32_t nameBuffLen) { char nameBuffer[OBJECT_NAME_MAX_LEN] = {'\0'}; - int32_t res = strcpy_s(nameBuffer, OBJECT_NAME_MAX_LEN, HcsGetModuleName()); - PRINTF_CHECK_AND_RETURN(res); + if (strcpy_s(nameBuffer, OBJECT_NAME_MAX_LEN, HcsGetModuleName()) != EOK) { + return EOUTPUT; + } ToUpperCamelString(nameBuffer, strlen(nameBuffer)); - res = sprintf_s(name, nameBuffLen, "%s%s", g_namePrefix, nameBuffer); + int32_t res = sprintf_s(name, nameBuffLen, "%s%s", g_namePrefix, nameBuffer); PRINTF_CHECK_AND_RETURN(res); - res = strcpy_s(nameBuffer, OBJECT_NAME_MAX_LEN, node->configNode.name); - PRINTF_CHECK_AND_RETURN(res); + if (strcpy_s(nameBuffer, OBJECT_NAME_MAX_LEN, node->configNode.name) != EOK) { + return EOUTPUT; + } ToUpperCamelString(nameBuffer, strlen(nameBuffer)); res = sprintf_s(name + strlen(name), nameBuffLen - strlen(name), "%s", nameBuffer); PRINTF_CHECK_AND_RETURN(res); @@ -329,7 +327,7 @@ static int32_t GenConfigArrayName(ParserObject *array, char *name, uint32_t name char buffer[OBJECT_NAME_MAX_LEN] = {'\0'}; if (strcpy_s(buffer, sizeof(buffer), array->objectBase.name) != EOK) { - HCS_ERROR("%s: string copy fail", __func__); + HCS_ERROR("%s: failed to copy string", __func__); return EOUTPUT; } ToUpperCamelString(buffer, strlen(buffer)); @@ -376,32 +374,27 @@ static int32_t GetArraySize(const ParserObject *array) return size; } -static int32_t HcsPrintTermDefinition(char *buffer, uint32_t bufferSize, const ParserObject *object) +static int32_t HcsPrintTermDefinition(const ParserObject *object) { ParserObject *termContext = (ParserObject *)object->objectBase.child; - int32_t res; + int32_t res = NOERR; switch (termContext->objectBase.type) { case PARSEROP_ARRAY: if (HcsIsInTemplateNode(object)) { - res = sprintf_s(buffer, bufferSize, "const %s *%s;\n", GetArrayType(termContext), - object->configTerm.name); - PRINTF_CHECK_AND_RETURN(res); - res = sprintf_s(buffer + strlen(buffer), bufferSize - strlen(buffer), "%*cuint32_t %sSize;\n", TAB_SIZE, - ' ', object->configTerm.name); + res = HcsFormatOutputWrite("const %s *%s;\n", GetArrayType(termContext), object->configTerm.name); + OUTPUT_CHECK_AND_RETURN(res); + res = HcsFormatOutputWrite("%*cuint32_t %sSize;\n", TAB_SIZE, ' ', object->configTerm.name); } else { - res = sprintf_s(buffer, bufferSize, "%s %s[%d];\n", GetArrayType(termContext), object->configTerm.name, + res = HcsFormatOutputWrite("%s %s[%d];\n", GetArrayType(termContext), object->configTerm.name, GetArraySize(termContext)); } - PRINTF_CHECK_AND_RETURN(res); break; case PARSEROP_UINT8: case PARSEROP_UINT16: case PARSEROP_UINT32: case PARSEROP_UINT64: case PARSEROP_STRING: - res = sprintf_s(buffer, bufferSize - strlen(buffer), "%s %s;\n", g_typeMap[termContext->objectBase.type], - object->configTerm.name); - PRINTF_CHECK_AND_RETURN(res); + res = HcsFormatOutputWrite("%s %s;\n", g_typeMap[termContext->objectBase.type], object->configTerm.name); break; case PARSEROP_NODEREF: { char refType[OBJECT_NAME_MAX_LEN] = {'\0'}; @@ -409,15 +402,13 @@ static int32_t HcsPrintTermDefinition(char *buffer, uint32_t bufferSize, const P if (res) { return res; } - res = sprintf_s(buffer, bufferSize - strlen(buffer), "const struct %s* %s;\n", refType, - object->configTerm.name); - PRINTF_CHECK_AND_RETURN(res); + res = HcsFormatOutputWrite("const struct %s* %s;\n", refType, object->configTerm.name); } break; default: break; } - return NOERR; + return res; } static int32_t HcsObjectDefinitionGen(const ParserObject *current) @@ -426,9 +417,8 @@ static int32_t HcsObjectDefinitionGen(const ParserObject *current) return NOERR; } - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; - int32_t res = sprintf_s(writeBuffer, WRITE_BUFFER_LEN, "%*c", TAB_SIZE, ' '); - PRINTF_CHECK_AND_RETURN(res); + int res = NOERR; + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c", TAB_SIZE, ' ')); switch (current->objectBase.type) { case PARSEROP_CONFNODE: { char structName[OBJECT_NAME_MAX_LEN] = {'\0'}; @@ -438,32 +428,27 @@ static int32_t HcsObjectDefinitionGen(const ParserObject *current) } if (current->configNode.nodeType == CONFIG_NODE_TEMPLATE) { char nodeName[OBJECT_NAME_MAX_LEN] = {0}; - if (strcpy_s(nodeName, sizeof(nodeName), current->configNode.name)) { + if (strcpy_s(nodeName, sizeof(nodeName), current->configNode.name) != EOK) { return EOUTPUT; } ToLowerCamelString(nodeName, strlen(nodeName)); - res = sprintf_s(writeBuffer + TAB_SIZE, WRITE_BUFFER_LEN - strlen(writeBuffer), - "const struct %s* %s;\n", structName, nodeName); - PRINTF_CHECK_AND_RETURN(res); - res = sprintf_s(writeBuffer + strlen(writeBuffer), WRITE_BUFFER_LEN - strlen(writeBuffer), - "%*cuint16_t %sSize;\n", TAB_SIZE, ' ', nodeName); + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("const struct %s* %s;\n", structName, nodeName)); + res = HcsFormatOutputWrite("%*cuint16_t %sSize;\n", TAB_SIZE, ' ', nodeName); } else if (current->configNode.nodeType == CONFIG_NODE_INHERIT) { return NOERR; } else { - res = sprintf_s(writeBuffer + TAB_SIZE, WRITE_BUFFER_LEN - strlen(writeBuffer), "struct %s %s;\n", - structName, current->configNode.name); + res = HcsFormatOutputWrite("struct %s %s;\n", structName, current->configNode.name); } - PRINTF_CHECK_AND_RETURN(res); break; } case PARSEROP_CONFTERM: - HcsPrintTermDefinition(writeBuffer + TAB_SIZE, WRITE_BUFFER_LEN - strlen(writeBuffer), current); + res = HcsPrintTermDefinition(current); break; default: break; } - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); + return res; } static int32_t HcsDuplicateCheckWalkCallBack(ParserObject *current, int32_t walkDepth) @@ -479,7 +464,6 @@ static int32_t HcsDuplicateCheckWalkCallBack(ParserObject *current, int32_t walk static int32_t HcsGenNormalNodeDefinition(ParserObject *object, int32_t walkDepth) { (void)walkDepth; - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; char structName[OBJECT_NAME_MAX_LEN] = {'\0'}; int32_t res = GenConfigStructName(object, structName, OBJECT_NAME_MAX_LEN - 1); if (res) { @@ -491,11 +475,7 @@ static int32_t HcsGenNormalNodeDefinition(ParserObject *object, int32_t walkDept HcsSymbolTableAdd(structName, object); } - res = sprintf_s(writeBuffer, (WRITE_BUFFER_LEN - 1), "struct %s {\n", structName); - PRINTF_CHECK_AND_RETURN(res); - if (HcsOutputWrite(writeBuffer, strlen(writeBuffer))) { - return EOUTPUT; - } + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("struct %s {\n", structName)); ParserObject *terms = (ParserObject *)object->objectBase.child; while (terms != NULL) { @@ -506,10 +486,7 @@ static int32_t HcsGenNormalNodeDefinition(ParserObject *object, int32_t walkDept terms = (ParserObject *)terms->objectBase.next; } - res = sprintf_s(writeBuffer, (WRITE_BUFFER_LEN - 1), "};\n\n"); - PRINTF_CHECK_AND_RETURN(res); - - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); + return HcsFormatOutputWrite("};\n\n"); } static int32_t HcsGenNodeTemplateDefinition(ParserObject *object, int32_t walkDepth) @@ -532,20 +509,18 @@ static int32_t HcsDefinitionGenWalkCallBack(ParserObject *current, int32_t walkD } } -static uint32_t HcsPrintTermValue(char *buffer, uint32_t buffSize, const ParserObject *object) +static uint32_t HcsPrintTermValue(const ParserObject *object) { - int32_t res = 0; + int32_t res = NOERR; switch (object->objectBase.type) { case PARSEROP_UINT8: /* fallthrough */ case PARSEROP_UINT16: /* fallthrough */ case PARSEROP_UINT32: /* fallthrough */ case PARSEROP_UINT64: - res = sprintf_s(buffer, buffSize, "0x%" PRIx64, object->objectBase.integerValue); - PRINTF_CHECK_AND_RETURN(res); + res = HcsFormatOutputWrite("0x%" PRIx64, object->objectBase.integerValue); break; case PARSEROP_STRING: - res = sprintf_s(buffer, buffSize, "\"%s\"", object->objectBase.stringValue); - PRINTF_CHECK_AND_RETURN(res); + res = HcsFormatOutputWrite("\"%s\"", object->objectBase.stringValue); break; default: break; @@ -603,19 +578,15 @@ static char *HcsBuildObjectPath(const ParserObject *refObject) return path; } -static int32_t HcsPrintArrayImplInSubClass(char *buffer, uint32_t bufferSize, ParserObject *object, uint8_t tabSize) +static int32_t HcsPrintArrayImplInSubClass(ParserObject *object, uint8_t tabSize) { - int32_t size = sprintf_s(buffer, bufferSize, "%*c.%s = ", tabSize, ' ', object->objectBase.name); - PRINTF_CHECK_AND_RETURN(size); - if (GenConfigArrayName(object, buffer + size, bufferSize - size)) { + char arrayName[VARIABLE_NAME_LEN] = {0}; + if (GenConfigArrayName(object, arrayName, VARIABLE_NAME_LEN)) { return EOUTPUT; } - size = sprintf_s(buffer + strlen(buffer), bufferSize - strlen(buffer), ",\n"); - PRINTF_CHECK_AND_RETURN(size); - size = sprintf_s(buffer + strlen(buffer), bufferSize - strlen(buffer), "%*c.%sSize = %d,\n", tabSize, ' ', - object->configTerm.name, GetArraySize((ParserObject *)object->objectBase.child)); - PRINTF_CHECK_AND_RETURN(size); - return HcsOutputWrite(buffer, strlen(buffer)); + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = %s,\n", object->objectBase.name, arrayName)); + return HcsFormatOutputWrite("%*c.%sSize = %d,\n", tabSize, ' ', + object->configTerm.name, GetArraySize((ParserObject *)object->objectBase.child)); } static int32_t HcsPrintArrayContent(const ParserObject *object, int32_t tabSize) @@ -624,59 +595,44 @@ static int32_t HcsPrintArrayContent(const ParserObject *object, int32_t tabSize) return NOERR; } - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; ParserObject *element = (ParserObject *)object->objectBase.child; - uint32_t writeSize = 0; + uint32_t elementCount = 0; while (element != NULL) { - int32_t size = HcsPrintTermValue(writeBuffer + writeSize, sizeof(writeBuffer) - writeSize, element); - writeBuffer[writeSize + size++] = ','; - writeBuffer[writeSize + size++] = ' '; - writeSize += size; - if (writeSize >= GEN_CODE_MARGIN_SIZE) { - writeSize -= 1; /* strip space at line end */ - size = sprintf_s(writeBuffer + writeSize, sizeof(writeBuffer) - writeSize, "\n%*c", tabSize, ' '); - PRINTF_CHECK_AND_RETURN(size); - writeSize += size; - if (HcsOutputWrite(writeBuffer, writeSize)) { - return EOUTPUT; - } - writeSize = 0; + if (HcsPrintTermValue(element) != NOERR) { + return EOUTPUT; + } + if (elementCount++ >= ELEMENT_PER_LINE) { + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("\n%*c", tabSize, ' ')); } element = (ParserObject *)element->configTerm.next; + if (element != NULL) { + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(", ")); + } } - return writeSize ? HcsOutputWrite(writeBuffer, writeSize - GEN_ARRAY_SEP_SIZE) : NOERR; + return NOERR; } -static int32_t HcsPrintArrayImplement(char *buffer, uint32_t bufferSize, ParserObject *object, uint8_t tabSize) +static int32_t HcsPrintArrayImplement(ParserObject *object, uint8_t tabSize) { if (HcsIsInSubClassNode(object)) { - return HcsPrintArrayImplInSubClass(buffer, bufferSize, object, tabSize); + return HcsPrintArrayImplInSubClass(object, tabSize); } ParserObject *termContext = (ParserObject *)object->objectBase.child; - int32_t res = sprintf_s(buffer + strlen(buffer), bufferSize - strlen(buffer), "%*c.%s = { ", tabSize, ' ', - object->configTerm.name); - PRINTF_CHECK_AND_RETURN(res); - if (HcsOutputWrite(buffer, strlen(buffer))) { - return EOUTPUT; - } + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = { ", object->configTerm.name)); + if (HcsPrintArrayContent(termContext, tabSize + TAB_SIZE)) { HCS_ERROR("fail to write array content"); return EOUTPUT; } - res = sprintf_s(buffer, bufferSize, " },\n"); - PRINTF_CHECK_AND_RETURN(res); - if (HcsOutputWrite(buffer, strlen(buffer))) { - return EOUTPUT; - } - return NOERR; + return HcsFormatOutputWrite(" },\n"); } -static int32_t HcsPrintTermImplement(char *buffer, uint32_t bufferSize, ParserObject *object, int32_t tabSize) +static int32_t HcsPrintTermImplement(ParserObject *object, int32_t tabSize) { - int32_t res; - sprintf_s(buffer, bufferSize, "%*c", tabSize, ' '); + int32_t res = NOERR; + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c", tabSize, ' ')); ParserObject *termContext = (ParserObject *)object->objectBase.child; switch (termContext->objectBase.type) { case PARSEROP_UINT8: @@ -686,52 +642,43 @@ static int32_t HcsPrintTermImplement(char *buffer, uint32_t bufferSize, ParserOb case PARSEROP_UINT32: /* fall-through */ case PARSEROP_UINT64: - res = sprintf_s(buffer + strlen(buffer), bufferSize - strlen(buffer), ".%s = ", object->configTerm.name); - PRINTF_CHECK_AND_RETURN(res); - if (!HcsPrintTermValue(buffer + strlen(buffer), bufferSize - strlen(buffer), termContext)) { + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = ", object->configTerm.name)); + if (HcsPrintTermValue(termContext) != NOERR) { return EOUTPUT; } - res = sprintf_s(buffer + strlen(buffer), bufferSize - strlen(buffer), ",\n"); - PRINTF_CHECK_AND_RETURN(res); + res = HcsFormatOutputWrite(",\n"); break; case PARSEROP_STRING: - res = sprintf_s(buffer + strlen(buffer), bufferSize - strlen(buffer), ".%s = ", object->configTerm.name); - PRINTF_CHECK_AND_RETURN(res); - if (!HcsPrintTermValue(buffer + strlen(buffer), bufferSize - strlen(buffer), termContext)) { + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = ", object->configTerm.name)); + if (HcsPrintTermValue(termContext) != NOERR) { return EOUTPUT; } - res = sprintf_s(buffer + strlen(buffer), bufferSize - strlen(buffer), ",\n"); - PRINTF_CHECK_AND_RETURN(res); + res = HcsFormatOutputWrite(",\n"); break; case PARSEROP_ARRAY: - if (HcsPrintArrayImplement(buffer + strlen(buffer), bufferSize - strlen(buffer), object, tabSize)) { - return EOUTPUT; - } - buffer[0] = '\0'; + res = HcsPrintArrayImplement(object, tabSize); break; case PARSEROP_NODEREF: { char *refPath = HcsBuildObjectPath((ParserObject *)object->objectBase.child->value); if (refPath == NULL) { return EOUTPUT; } - res = sprintf_s(buffer + strlen(buffer), bufferSize - strlen(buffer), ".%s = &%s,\n", - object->configTerm.name, refPath); + res = HcsFormatOutputWrite(".%s = &%s,\n", object->configTerm.name, refPath); HcsMemFree(refPath); - PRINTF_CHECK_AND_RETURN(res); break; } default: break; } - return NOERR; + return res; } static int32_t HcsGenTemplateVariableName(ParserObject *object, char *nameBuff, uint32_t nameBufferSize) { char tempName[OBJECT_NAME_MAX_LEN] = {'\0'}; - if (strcpy_s(tempName, sizeof(tempName), object->objectBase.name)) { - HCS_ERROR("s: string copy fail"); + if (strcpy_s(tempName, sizeof(tempName), object->objectBase.name) != EOK) { + HCS_ERROR("failed to copy string"); return EOUTPUT; } ToUpperCamelString(tempName, sizeof(tempName)); @@ -756,24 +703,22 @@ static int32_t HcsGenTemplateVariableName(ParserObject *object, char *nameBuff, static int32_t HcsTemplateNodeImplGen(ParserObject *current, int32_t tabSize) { - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; char templateVariableName[VARIABLE_NAME_LEN] = {'\0'}; if (HcsGenTemplateVariableName(current, templateVariableName, sizeof(templateVariableName))) { return EOUTPUT; } char nodeName[OBJECT_NAME_MAX_LEN] = {0}; - if (strcpy_s(nodeName, sizeof(nodeName), current->configNode.name)) { - HCS_ERROR("%s: string copy fail", __func__); + if (strcpy_s(nodeName, sizeof(nodeName), current->configNode.name) != EOK) { + HCS_ERROR("%s: failed to copy string", __func__); return EOUTPUT; } + ToLowerCamelString(nodeName, strlen(nodeName)); - int32_t res = sprintf_s(writeBuffer, WRITE_BUFFER_LEN, "%*c.%s = %s,\n", tabSize, ' ', nodeName, - current->configNode.inheritCount ? templateVariableName : "0"); - PRINTF_CHECK_AND_RETURN(res); - res = sprintf_s(writeBuffer + strlen(writeBuffer), WRITE_BUFFER_LEN - strlen(writeBuffer), "%*c.%sSize = %d,\n", + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c.%s = %s,\n", tabSize, ' ', nodeName, + current->configNode.inheritCount ? templateVariableName : "0")); + + return HcsFormatOutputWrite("%*c.%sSize = %d,\n", tabSize, ' ', nodeName, current->configNode.inheritCount); - PRINTF_CHECK_AND_RETURN(res); - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); } static int32_t HcsInheritObjectImplGen(ParserObject *current, int32_t tabSize) @@ -787,33 +732,26 @@ static int32_t HcsInheritObjectImplGen(ParserObject *current, int32_t tabSize) static int32_t HcsObjectImplementGen(ParserObject *current, int32_t tabSize) { - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; - int32_t res; + int32_t res = NOERR; switch (current->objectBase.type) { - case PARSEROP_CONFNODE: { + case PARSEROP_CONFNODE: if (current->configNode.nodeType != CONFIG_NODE_NOREF) { res = HcsInheritObjectImplGen(current, tabSize); return res ? res : EASTWALKBREAK; } - res = sprintf_s(writeBuffer, WRITE_BUFFER_LEN, "%*c.%s = {\n", tabSize, ' ', current->configNode.name); - PRINTF_CHECK_AND_RETURN(res); + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c.%s = {\n", tabSize, ' ', current->configNode.name)); if (current->objectBase.child == NULL) { - res = sprintf_s(writeBuffer + strlen(writeBuffer) - 1, WRITE_BUFFER_LEN - strlen(writeBuffer) + 1, - "},\n"); - PRINTF_CHECK_AND_RETURN(res); + res = HcsFormatOutputWrite("%*c},\n", tabSize, ' '); } - } break; + break; case PARSEROP_CONFTERM: - res = HcsPrintTermImplement(writeBuffer, WRITE_BUFFER_LEN, current, tabSize); - if (res) { - return res; - } + res = HcsPrintTermImplement(current, tabSize); break; default: return NOERR; } - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); + return res; } static int32_t HcsImplementGenWalkCallBack(ParserObject *current, int32_t walkDepth) @@ -827,20 +765,17 @@ static int32_t HcsImplementGenWalkCallBack(ParserObject *current, int32_t walkDe } if (current == HcsGetParserRoot()) { - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; char structName[OBJECT_NAME_MAX_LEN] = {'\0'}; int32_t res = GenConfigStructName(current, structName, OBJECT_NAME_MAX_LEN - 1); if (res) { return res; } - res = sprintf_s(writeBuffer, WRITE_BUFFER_LEN, "static const struct %s %s = {\n", structName, - GetConfigRootVariableName()); - PRINTF_CHECK_AND_RETURN(res); + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("static const struct %s %s = {\n", + structName, GetConfigRootVariableName())); if (current->objectBase.child == NULL) { - res = sprintf_s(writeBuffer + strlen(writeBuffer), WRITE_BUFFER_LEN - strlen(writeBuffer), "};\n"); - PRINTF_CHECK_AND_RETURN(res); + res = HcsFormatOutputWrite("};\n"); } - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); + return res; } return HcsObjectImplementGen(current, walkDepth * TAB_SIZE); } @@ -856,18 +791,12 @@ static int32_t HcsImplementCloseBraceGen(ParserObject *current, int32_t walkDept } int32_t tabSize = walkDepth * TAB_SIZE; - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; - int32_t res; if (current != HcsGetParserRoot()) { - res = sprintf_s(writeBuffer, WRITE_BUFFER_LEN, "%*c},\n", tabSize, ' '); - PRINTF_CHECK_AND_RETURN(res); + return HcsFormatOutputWrite("%*c},\n", tabSize, ' '); } else { - res = sprintf_s(writeBuffer, WRITE_BUFFER_LEN, "};\n"); - PRINTF_CHECK_AND_RETURN(res); + return HcsFormatOutputWrite("};\n"); } - - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); } static void ToUpperString(char *str, uint32_t strLen) @@ -877,118 +806,71 @@ static void ToUpperString(char *str, uint32_t strLen) } } -static void StripFileNameSuffix(char *fileName, uint32_t fileNameLen) -{ - for (uint32_t i = 0; i < fileNameLen; ++i) { - if (fileName[i] == '.') { - fileName[i] = '\0'; - break; - } - } -} - #define HCS_HEADER_MACRO_MAX_LEN 150 static char *GenHeaderProtectionMacro() { - const char *outPutFileName = HcsGetStripedOutputFileName(); - char *headerMacro = strdup(outPutFileName); - if (headerMacro == NULL) { - HCS_ERROR("oom"); + char *fileName = HcsGetOutputFileNameWithoutSuffix(); + if (fileName == NULL) { return NULL; } - StripFileNameSuffix(headerMacro, strlen(headerMacro)); - ToUpperString(headerMacro, strlen(headerMacro)); + ToUpperString(fileName, strlen(fileName)); char *macro = HcsMemZalloc(sizeof(char) * HCS_HEADER_MACRO_MAX_LEN); if (macro == NULL) { HCS_ERROR("oom"); - HcsMemFree(headerMacro); + HcsMemFree(fileName); return NULL; } - int32_t res = sprintf_s(macro, HCS_HEADER_MACRO_MAX_LEN, "HCS_CONFIG_%s_HEADER_H", headerMacro); + int32_t res = sprintf_s(macro, HCS_HEADER_MACRO_MAX_LEN, "HCS_CONFIG_%s_HEADER_H", fileName); + HcsMemFree(fileName); if (res <= 0) { - HcsMemFree(headerMacro); HcsMemFree(macro); return NULL; } - HcsMemFree(headerMacro); return macro; } static int32_t HcsWriteHeaderFileHead() { /* Write copyright info */ - const char *header = HCS_CONFIG_FILE_HEADER; - if (HcsOutputWrite(header, strlen(header))) { - return EOUTPUT; - } + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(HCS_CONFIG_FILE_HEADER)); /* Write header protection macro */ char *headerProtectMacro = GenHeaderProtectionMacro(); if (headerProtectMacro == NULL) { return EOUTPUT; } - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; - int32_t ret = sprintf_s(writeBuffer, WRITE_BUFFER_LEN, "#ifndef %s\n#define %s\n\n", - headerProtectMacro, headerProtectMacro); - HcsMemFree(headerProtectMacro); - if (ret <= 0) { - return EOUTPUT; - } - - if (HcsOutputWrite(writeBuffer, strlen(writeBuffer))) { - return EOUTPUT; - } + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("#ifndef %s\n#define %s\n\n", + headerProtectMacro, headerProtectMacro)); /* Write include header file */ - header = HCS_CONFIG_INCLUDE_HEADER; - if (HcsOutputWrite(header, strlen(header))) { - return EOUTPUT; - } - - return NOERR; + return HcsFormatOutputWrite(HCS_CONFIG_INCLUDE_HEADER); } static int32_t HcsWriteHeaderFileEnd() { - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; /* Write header protection macro */ char *headerMacro = GenHeaderProtectionMacro(); if (headerMacro == NULL) { return EOUTPUT; } - int32_t ret = sprintf_s(writeBuffer, (WRITE_BUFFER_LEN - 1), "#endif // %s", headerMacro); + int32_t ret = HcsFormatOutputWrite("\n\n#endif // %s", headerMacro); HcsMemFree(headerMacro); - if (ret <= 0) { - return EOUTPUT; - } - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); + return ret; } static int32_t HcsWriteFunctionDeclaration() { - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; - int32_t ret = sprintf_s(writeBuffer, (WRITE_BUFFER_LEN - 1), HCS_CONFIG_INCLUDE_FUNC_DECLARATION, g_namePrefix, + return HcsFormatOutputWrite("const struct %s%sRoot* HdfGet%sModuleConfigRoot(void);", g_namePrefix, g_bigHumpModuleName, g_bigHumpModuleName); - if (ret <= 0) { - return EOUTPUT; - } - - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); } static int32_t HcsWriteFunctionImplement() { - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; - int32_t ret = sprintf_s(writeBuffer, (WRITE_BUFFER_LEN - 1), HCS_CONFIG_FUNC_IMPLEMENT, g_namePrefix, + return HcsFormatOutputWrite(HCS_CONFIG_FUNC_IMPLEMENT, g_namePrefix, g_bigHumpModuleName, g_bigHumpModuleName, GetConfigRootVariableName()); - if (ret <= 0) { - return EOUTPUT; - } - - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); } static int32_t HcsOutputHeaderFile() @@ -1064,47 +946,33 @@ static int32_t HcsTemplateImplGenWalkCallBack(ParserObject *current, int32_t wal return NOERR; } - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; char nameBuff[OBJECT_NAME_MAX_LEN] = {'\0'}; int32_t res = GenConfigStructName(current, nameBuff, OBJECT_NAME_MAX_LEN - 1); if (res) { return res; } - res = sprintf_s(writeBuffer, sizeof(writeBuffer), "static const struct %s ", nameBuff); - PRINTF_CHECK_AND_RETURN(res); + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("static const struct %s ", nameBuff)); if (HcsGenTemplateVariableName(current, nameBuff, sizeof(nameBuff))) { return EOUTPUT; } - res = sprintf_s(writeBuffer + strlen(writeBuffer), sizeof(writeBuffer) - strlen(writeBuffer), - "%s[] = {\n", nameBuff); - PRINTF_CHECK_AND_RETURN(res); - HcsOutputWrite(writeBuffer, strlen(writeBuffer)); - /* Generate C global variables definition file */ + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%s[] = {\n", nameBuff)); + /* Generate C global variables definition file */ TemplateNodeInstance *subClasses = current->configNode.subClasses; g_baseTabsize = TAB_SIZE + TAB_SIZE; while (subClasses != NULL) { - res = sprintf_s(writeBuffer, sizeof(writeBuffer), "%*c[%d] = {\n", TAB_SIZE, ' ', - subClasses->nodeObject->inheritIndex); - PRINTF_CHECK_AND_RETURN(res); - if (HcsOutputWrite(writeBuffer, res)) { - return EOUTPUT; - } + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c[%d] = {\n", TAB_SIZE, ' ', + subClasses->nodeObject->inheritIndex)); + if (HcsTemplateVariableGen((ParserObject *)subClasses->nodeObject)) { return EOUTPUT; } - res = sprintf_s(writeBuffer, sizeof(writeBuffer), "%*c},\n", TAB_SIZE, ' '); - PRINTF_CHECK_AND_RETURN(res); - if (HcsOutputWrite(writeBuffer, strlen(writeBuffer))) { - return EOUTPUT; - } + OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c},\n", TAB_SIZE, ' ')); subClasses = subClasses->next; } - res = sprintf_s(writeBuffer, sizeof(writeBuffer), "};\n\n"); - PRINTF_CHECK_AND_RETURN(res); - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); + return HcsFormatOutputWrite("};\n\n"); } static int32_t HcsArrayVariablesDeclareGen(ParserObject *term) @@ -1113,26 +981,21 @@ static int32_t HcsArrayVariablesDeclareGen(ParserObject *term) return NOERR; } - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; char nameBuff[OBJECT_NAME_MAX_LEN] = {'\0'}; int32_t res = GenConfigArrayName(term, nameBuff, OBJECT_NAME_MAX_LEN - 1); if (res) { return res; } ParserObject *array = (ParserObject *)term->configTerm.child; - res = sprintf_s(writeBuffer, sizeof(writeBuffer), "\nstatic const %s %s[%d] = {\n%*c", GetArrayType(array), + res = HcsFormatOutputWrite("\nstatic const %s %s[%d] = {\n%*c", GetArrayType(array), nameBuff, GetArraySize(array), TAB_SIZE, ' '); - PRINTF_CHECK_AND_RETURN(res); - if (HcsOutputWrite(writeBuffer, strlen(writeBuffer))) { - return EOUTPUT; - } + OUTPUT_CHECK_AND_RETURN(res); + if (HcsPrintArrayContent(array, TAB_SIZE)) { HCS_ERROR("fail to write array content"); return EOUTPUT; } - res = sprintf_s(writeBuffer, sizeof(writeBuffer), "\n};\n"); - PRINTF_CHECK_AND_RETURN(res); - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); + return HcsFormatOutputWrite("\n};\n"); } static int32_t HcsTemplateVariablesDeclareGenWalk(ParserObject *current, int32_t walkDepth) @@ -1174,10 +1037,8 @@ static int32_t HcsTemplateVariablesDeclareGen(ParserObject *astRoot) /* if no template variable generated, should not output end line */ return NOERR; } - char writeBuffer[WRITE_BUFFER_LEN] = {'\0'}; - int32_t res = sprintf_s(writeBuffer, sizeof(writeBuffer), "\n"); - PRINTF_CHECK_AND_RETURN(res); - return HcsOutputWrite(writeBuffer, strlen(writeBuffer)); + const char *lineEnd = "\n"; + return HcsOutputWrite(lineEnd, strlen(lineEnd)); } static int32_t HcsOutputTemplateImplement(ParserObject *astRoot) @@ -1206,32 +1067,24 @@ static int32_t HcsOutputCFile() return EINVALF; } - const char *header = HCS_CONFIG_FILE_HEADER; - if (HcsOutputWrite(header, strlen(header))) { + if (HcsFormatOutputWrite(HCS_CONFIG_FILE_HEADER)) { HcsCloseOutput(outputFIle); return EOUTPUT; } - char include[INCLUDE_PATH_MAX_LEN] = {'\0'}; - int32_t res = sprintf_s(include, INCLUDE_PATH_MAX_LEN, "#include \"%s", HcsGetStripedOutputFileName()); - if (res <= 0) { - HcsCloseOutput(outputFIle); + char *fileName = HcsGetOutputFileNameWithoutSuffix(); + if (fileName == NULL) { return EOUTPUT; } - - res = sprintf_s(include + strlen(include) - 1, WRITE_BUFFER_LEN - strlen(include), "h\"\n\n"); - if (res <= 0) { - HcsCloseOutput(outputFIle); - return EOUTPUT; - } - - if (HcsOutputWrite(include, strlen(include))) { + int32_t res = HcsFormatOutputWrite("#include \"%s.h\"\n\n", fileName); + HcsMemFree(fileName); + if (res != NOERR) { HcsCloseOutput(outputFIle); return EOUTPUT; } res = HcsOutputTemplateImplement(astRoot); - if (res) { + if (res != NOERR) { HcsCloseOutput(outputFIle); return EOUTPUT; } @@ -1248,7 +1101,7 @@ static int32_t HcsOutputCFile() return res; } -int32_t HcsTextCodeOutput() +int32_t HcsTextCodeOutput(void) { int32_t ret = HcsSymbolTableInit(); if (ret) { From f19742cab9d53de5096269c678da322a1184ecf7 Mon Sep 17 00:00:00 2001 From: zianed Date: Wed, 19 May 2021 11:59:27 +0800 Subject: [PATCH 12/21] modify wlan --- model/network/common/netdevice/net_device.c | 23 +++++++++++---------- model/network/wifi/core/hdf_wifi_core.c | 16 +++++++------- model/network/wifi/core/hdf_wifi_core.h | 4 ++-- support/posix/src/osal_thread.c | 6 ++++-- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/model/network/common/netdevice/net_device.c b/model/network/common/netdevice/net_device.c index 2a336b30..da504d16 100644 --- a/model/network/common/netdevice/net_device.c +++ b/model/network/common/netdevice/net_device.c @@ -17,12 +17,12 @@ static struct NetDeviceImpl *g_netDeviceImplTable[MAX_NETDEVICE_COUNT] = {NULL}; -static bool FindAvailableTable(uint32_t *index) +static bool FindAvailableTable(int32_t *index) { - uint32_t i; + int32_t i; if (index == NULL) { - HDF_LOGE("%s Find Available table index error!", __func__); + HDF_LOGE("Find Available table index error!"); return false; } for (i = 0; i < MAX_NETDEVICE_COUNT; i++) { @@ -34,7 +34,7 @@ static bool FindAvailableTable(uint32_t *index) return false; } -static bool AddNetDeviceImplToTable(uint32_t index, struct NetDeviceImpl *netDeviceImpl) +static bool AddNetDeviceImplToTable(int32_t index, struct NetDeviceImpl *netDeviceImpl) { if (index >= MAX_NETDEVICE_COUNT) { HDF_LOGE("%s error because of not enough space!", __func__); @@ -68,6 +68,7 @@ static struct NetDeviceImpl *InitNetDeviceImpl(NetDevice *nd, NetIfCategory ifCa HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); return NULL; } + (void)memset_s(ndImpl, sizeof(struct NetDeviceImpl), 0, sizeof(struct NetDeviceImpl)); ndImpl->netDevice = nd; if (RegisterNetDeviceImpl(ndImpl) != HDF_SUCCESS) { @@ -99,7 +100,6 @@ static void DeInitNetDeviceImpl(struct NetDeviceImpl *netDeviceImpl) /* last release netDeviceImpl */ OsalMemFree(netDeviceImpl); - netDeviceImpl = NULL; HDF_LOGI("%s success!", __func__); return; } @@ -117,7 +117,7 @@ static struct NetDeviceImpl *GetImplByNetDevice(const struct NetDevice *netDevic } } } - HDF_LOGE("%s Get Impl by netdevice failed", __func__); + HDF_LOGE("Don't Get Impl by netdevice"); return ndImpl; } @@ -125,7 +125,7 @@ struct NetDevice *NetDeviceInit(const char *ifName, uint32_t len, NetIfCategory { NetDevice *netDevice = NULL; struct NetDeviceImpl *ndImpl = NULL; - uint32_t index = 0; + int32_t index = 0; int32_t ret; if ((ifName == NULL) || (strlen(ifName) != len) || (strlen(ifName) > IFNAMSIZ - 1)) { @@ -137,8 +137,9 @@ struct NetDevice *NetDeviceInit(const char *ifName, uint32_t len, NetIfCategory HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); return NULL; } - if (strcpy_s(netDevice->name, IFNAMSIZ, ifName) != EOK) { - HDF_LOGE("%s fail: strcpy_s fail!", __func__); + (void)memset_s(netDevice, sizeof(NetDevice), 0, sizeof(NetDevice)); + if (memcpy_s(netDevice->name, IFNAMSIZ, ifName, len + 1) != EOK) { + HDF_LOGE("%s fail: memcpy_s fail!", __func__); OsalMemFree(netDevice); return NULL; } @@ -317,7 +318,7 @@ static int32_t NetIfRxImpl(const struct NetDevice *netDevice, NetBuf *buff, Rece ProcessingResult ret = PROCESSING_CONTINUE; if (ndImpl == NULL || ndImpl->interFace == NULL || ndImpl->interFace->receive == NULL) { - HDF_LOGE("%s: NetIfRxImpl fail : netdevice not exist!", __func__); + HDF_LOGE("NetIfRxImpl fail : netdevice not exist!"); return HDF_ERR_INVALID_PARAM; } @@ -332,7 +333,7 @@ static int32_t NetIfRxImpl(const struct NetDevice *netDevice, NetBuf *buff, Rece HDF_LOGI("NetIfRxImpl specialEtherType Process not need TCP/IP stack!"); return HDF_SUCCESS; } else { - HDF_LOGE("%s: NetIfRxImpl specialEtherType Process error", __func__); + HDF_LOGE("NetIfRxImpl specialEtherType Process error"); return HDF_FAILURE; } } diff --git a/model/network/wifi/core/hdf_wifi_core.c b/model/network/wifi/core/hdf_wifi_core.c index 75c26ae9..32179061 100644 --- a/model/network/wifi/core/hdf_wifi_core.c +++ b/model/network/wifi/core/hdf_wifi_core.c @@ -39,13 +39,13 @@ int32_t HdfWifiGetBusIdx(void) * @brief as for now, we just support one wlan module in one board cause driver binds to wlan featere * due to that reason, once we detected one chip, we stop rescan. */ -int32_t HdfWlanSdioScan(struct HdfWlanDevice *data, struct HdfConfigWlanBus *busConfig) +int HdfWlanSdioScan(struct HdfWlanDevice *data, struct HdfConfigWlanBus *busConfig) { /* get config vendId, deviceId and chip-name which used in detect match process */ HdfWlanGetSdioTableByConfig(); HdfWlanSdioScanTriggerByBusIndex(busConfig->busIdx); - int32_t ret = HdfWlanGetDetectedChip(data, busConfig); + int ret = HdfWlanGetDetectedChip(data, busConfig); HdfWlanSdioDriverUnReg(); if (ret != HDF_SUCCESS) { return ret; @@ -54,7 +54,7 @@ int32_t HdfWlanSdioScan(struct HdfWlanDevice *data, struct HdfConfigWlanBus *bus return HDF_SUCCESS; } -static int32_t HdfWifiDriverBind(struct HdfDeviceObject *dev) +static int HdfWifiDriverBind(struct HdfDeviceObject *dev) { ErrorCode errCode; static struct IDeviceIoService wifiService = { @@ -179,7 +179,7 @@ static struct HdfChipDriverFactory *HdfWlanGetDriverFactory(const char *driverNa static int32_t HdfWlanDeinitInterface(struct HdfWlanDevice *device, const char *ifName, struct HdfChipDriverFactory *factory) { - int32_t ret; + int ret; struct NetDevice *netdev = NULL; struct HdfChipDriver *chipDriver = NULL; @@ -369,7 +369,7 @@ static struct HdfWlanDevice *ProbeDevice(struct HdfConfigWlanDevInst *deviceConf return device; } -int32_t HdfWifiDeinitDevice(struct HdfWlanDevice *device) +int32_t DeinitDevice(struct HdfWlanDevice *device) { struct HdfChipDriverFactory *chipDriverFact = NULL; int32_t ret; @@ -394,7 +394,7 @@ int32_t HdfWifiDeinitDevice(struct HdfWlanDevice *device) return HDF_SUCCESS; } -int32_t HdfWifiInitDevice(struct HdfWlanDevice *device) +int32_t InitDevice(struct HdfWlanDevice *device) { int32_t ret; struct HdfChipDriverFactory *chipDriverFact = NULL; @@ -424,7 +424,7 @@ int32_t HdfWifiInitDevice(struct HdfWlanDevice *device) /* thread callback function */ static int32_t HdfWlanInitThread(void *para) { - const uint32_t initDelaySec = 15; + const uint32_t initDelaySec = 5; struct HdfDeviceObject *device = (struct HdfDeviceObject *)para; struct SubscriberCallback callback = { NULL }; struct HdfConfigWlanDeviceList *devList = NULL; @@ -465,7 +465,7 @@ static int32_t HdfWlanInitThread(void *para) // Load chip driver (void)DevSvcManagerClntSubscribeService(wlanDevice->driverName, callback); - (void)HdfWifiInitDevice(wlanDevice); + (void)InitDevice(wlanDevice); } HDF_LOGV("%s:finished.", __func__); diff --git a/model/network/wifi/core/hdf_wifi_core.h b/model/network/wifi/core/hdf_wifi_core.h index 78134dc5..c171fd61 100644 --- a/model/network/wifi/core/hdf_wifi_core.h +++ b/model/network/wifi/core/hdf_wifi_core.h @@ -17,9 +17,9 @@ extern "C" { #endif int32_t HdfWifiGetBusIdx(void); -int32_t HdfWifiDeinitDevice(struct HdfWlanDevice *device); +int32_t DeinitDevice(struct HdfWlanDevice *device); -int32_t HdfWifiInitDevice(struct HdfWlanDevice *device); +int32_t InitDevice(struct HdfWlanDevice *device); #ifdef __cplusplus } diff --git a/support/posix/src/osal_thread.c b/support/posix/src/osal_thread.c index bdf5e16c..fc621b42 100644 --- a/support/posix/src/osal_thread.c +++ b/support/posix/src/osal_thread.c @@ -12,6 +12,8 @@ #include "hdf_log.h" #include "osal_mem.h" +#define OSAL_PTHREAD_STACK_MIN 4096 + #define HDF_LOG_TAG osal_thread typedef void *(*PosixEntry)(void *data); @@ -73,7 +75,7 @@ int32_t OsalThreadCreate(struct OsalThread *thread, OsalThreadEntry threadEntry, int32_t OsalThreadDestroy(struct OsalThread *thread) { - if (thread != NULL && thread->realThread != NULL) { + if (thread->realThread != NULL) { OsalMemFree(thread->realThread); thread->realThread = NULL; } @@ -127,7 +129,7 @@ int32_t OsalThreadStart(struct OsalThread *thread, const struct OsalThreadParam size_t stackSize = param->stackSize; if (stackSize > 0) { - stackSize = (stackSize < PTHREAD_STACK_MIN) ? PTHREAD_STACK_MIN : stackSize; + stackSize = (stackSize < OSAL_PTHREAD_STACK_MIN) ? OSAL_PTHREAD_STACK_MIN : stackSize; resultCode = pthread_attr_setstacksize(&attribute, stackSize); if (resultCode != 0) { HDF_LOGE("pthread_attr_setstacksize errorno: %d", resultCode); From 994f76fbd6a4ebe9fbe4eb9bb75c329d8d93438a Mon Sep 17 00:00:00 2001 From: zianed Date: Wed, 19 May 2021 14:07:02 +0800 Subject: [PATCH 13/21] update support/posix/src/osal_thread.c. --- support/posix/src/osal_thread.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/support/posix/src/osal_thread.c b/support/posix/src/osal_thread.c index fc621b42..4fcfce15 100644 --- a/support/posix/src/osal_thread.c +++ b/support/posix/src/osal_thread.c @@ -12,7 +12,11 @@ #include "hdf_log.h" #include "osal_mem.h" +#ifndef PTHREAD_STACK_MIN #define OSAL_PTHREAD_STACK_MIN 4096 +#else +#define OSAL_PTHREAD_STACK_MIN PTHREAD_STACK_MIN +#endif #define HDF_LOG_TAG osal_thread From eb36af6ea73d2b5f1288aec94ffb3f5a73792281 Mon Sep 17 00:00:00 2001 From: yuanbo Date: Wed, 19 May 2021 16:19:54 +0800 Subject: [PATCH 14/21] fix ioservice event listener register issuewq --- ability/sbuf/include/hdf_sbuf.h | 2 +- core/adapter/syscall/src/hdf_syscall_adapter.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ability/sbuf/include/hdf_sbuf.h b/ability/sbuf/include/hdf_sbuf.h index 1ec26e85..cb6e1f41 100644 --- a/ability/sbuf/include/hdf_sbuf.h +++ b/ability/sbuf/include/hdf_sbuf.h @@ -9,7 +9,7 @@ * @addtogroup Core * @{ * - * @brief Provides functions to use the HarmonyOS Driver Foundation (HDF). + * @brief Provides functions to use the OpenHarmonyOS Driver Foundation (HDF). * * The HDF implements driver framework capabilities such as driver loading, service management, driver message model, * and power management. diff --git a/core/adapter/syscall/src/hdf_syscall_adapter.c b/core/adapter/syscall/src/hdf_syscall_adapter.c index c0d7bb60..be11c63e 100644 --- a/core/adapter/syscall/src/hdf_syscall_adapter.c +++ b/core/adapter/syscall/src/hdf_syscall_adapter.c @@ -799,7 +799,6 @@ int32_t HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDe if (adapter->group != NULL) { /* Do not bind any service in a service goup to its own thread or start the group thread. */ ret = HdfIoServiceGroupThreadStart(adapter->group); - DListRemove(&listener->listNode); OsalMutexUnlock(&adapter->mutex); return ret; } From 6555ebc27cdb60d3c037bc647a5c37a5a388d985 Mon Sep 17 00:00:00 2001 From: NickYang Date: Wed, 19 May 2021 19:52:53 +0800 Subject: [PATCH 15/21] sync l2weekly to l1 --- support/platform/src/dmac_core.c | 42 +++++++++++++++------------- support/platform/src/emmc_core.c | 34 +++++++++++----------- support/platform/src/emmc_if.c | 20 +++++-------- support/platform/src/i2c_if.c | 2 +- support/platform/src/mipi_dsi_core.c | 25 +++++++++-------- support/platform/src/rtc_base.c | 4 +-- support/platform/src/rtc_core.c | 2 +- support/platform/src/rtc_if.c | 4 +-- support/platform/src/sdio_core.c | 2 +- support/platform/src/spi_if.c | 18 ++++++------ support/platform/src/uart_core.c | 2 +- support/platform/src/uart_if.c | 2 +- 12 files changed, 79 insertions(+), 78 deletions(-) diff --git a/support/platform/src/dmac_core.c b/support/platform/src/dmac_core.c index 320fcf5c..b2b207b4 100644 --- a/support/platform/src/dmac_core.c +++ b/support/platform/src/dmac_core.c @@ -6,16 +6,17 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "dmac_core.h" #include #include "hdf_log.h" #include "osal_io.h" #include "osal_irq.h" #include "osal_mem.h" -#include "dmac_core.h" #define HDF_LOG_TAG dmac_core #define DMA_ALIGN_SIZE 256 +#define DMA_MAX_TRANS_SIZE_DEFAULT 256 static int DmacCheck(struct DmaCntlr *cntlr) { @@ -66,7 +67,7 @@ static void DmacFreeLli(struct DmacChanInfo *chanInfo) */ void DmaCntlrDestroy(struct DmaCntlr *cntlr) { - int i; + unsigned int i; if (cntlr == NULL || cntlr->channelNum > DMAC_CHAN_NUM_MAX) { HDF_LOGE("%s: cntlr null or channel invalid!", __func__); @@ -107,7 +108,7 @@ static void DmacCallbackHandle(struct DmacChanInfo *chanInfo) static int DmacWaitM2mSendComplete(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo) { - unsigned int ret; + uint32_t ret; if (DmacCheck(cntlr) != HDF_SUCCESS) { HDF_LOGE("check fail"); @@ -130,7 +131,7 @@ static int DmacWaitM2mSendComplete(struct DmaCntlr *cntlr, struct DmacChanInfo * static int DmacAllocateChannel(struct DmaCntlr *cntlr) { - unsigned int flags; + uint32_t flags; int i; if (DmacCheck(cntlr) != HDF_SUCCESS) { @@ -190,7 +191,7 @@ static struct DmacChanInfo *DmacRequestChannel(struct DmaCntlr *cntlr, HDF_LOGE("%s: get channel fail ret = %d", __func__, ret); return NULL; } - HDF_LOGD("channel = %d, transfer type = %d width = %u, config = 0x%x, lliflag = 0x%x", + HDF_LOGD("channel = %d, transfer type = %u width = %u, config = 0x%x, lliflag = 0x%x", ret, chanInfo->transferType, chanInfo->width, chanInfo->config, chanInfo->lliEnFlag); return chanInfo; } @@ -220,19 +221,13 @@ static int DmacFillLli(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, plli->count = cntlr->maxTransSize; } else { plli->nextLli = 0; - plli->count = (length % cntlr->maxTransSize); + plli->count = cntlr->maxTransSize == 0 ? length : (length % cntlr->maxTransSize); } plli->srcAddr = (long long)srcaddr; plli->destAddr = (long long)dstaddr; plli->config = chanInfo->config; - HDF_LOGD("plli->srcAddr = 0x%llx\n", plli->srcAddr); - HDF_LOGD("plli->destAddr = 0x%llx\n", plli->destAddr); - HDF_LOGD("plli->nextLli = 0x%llx\n", plli->nextLli); - HDF_LOGD("plli->config = 0x%x\n", plli->config); - HDF_LOGD("plli->count = 0x%x\n", plli->count); - if (chanInfo->transferType == TRASFER_TYPE_P2M) { dstaddr += plli->count; } else if (chanInfo->transferType == TRASFER_TYPE_M2P) { @@ -240,6 +235,7 @@ static int DmacFillLli(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, } plli++; } + plli = chanInfo->lli; cntlr->dmacCacheFlush((UINTPTR)plli, (UINTPTR)plli + (UINTPTR)(sizeof(struct DmacLli) * lliNum)); HDF_LOGD("alloc_addr = 0x%x, alloc_addr + (sizeof(DmacLli) * lli_num)= 0x%x\n", (UINTPTR)plli, (UINTPTR)plli + (UINTPTR)(sizeof(struct DmacLli) * lliNum)); @@ -369,6 +365,7 @@ static int DmacM2mTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg) return HDF_FAILURE; } if (dmaSize == 0) { + DmacFreeChannel(cntlr, chanInfo->channel); return HDF_FAILURE; } leftSize -= dmaSize; @@ -403,7 +400,7 @@ int32_t DmaCntlrTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg) } else if (msg->direct == TRASFER_TYPE_M2M) { return DmacM2mTransfer(cntlr, msg); } else { - HDF_LOGE("%s: invalid direct %d", __func__, msg->direct); + HDF_LOGE("%s: invalid direct %u", __func__, msg->direct); return HDF_FAILURE; } return DmacPeriphTransfer(cntlr, msg, periphAddr); @@ -419,7 +416,7 @@ unsigned int DmaGetCurrChanDestAddr(struct DmaCntlr *cntlr, unsigned int chan) return cntlr->dmacGetCurrDestAddr(cntlr, chan); } -static uint32_t DmacIsr(int irq, void *dev) +static uint32_t DmacIsr(uint32_t irq, void *dev) { struct DmaCntlr *cntlr = (struct DmaCntlr *)dev; unsigned int channelStatus; @@ -431,9 +428,9 @@ static uint32_t DmacIsr(int irq, void *dev) } if (irq != cntlr->irq || cntlr->channelNum > DMAC_CHAN_NUM_MAX) { - HDF_LOGE("%s: cntlr parm err! irq:%d, channel:%u", + HDF_LOGE("%s: cntlr param err! irq:%u, channel:%u", __func__, cntlr->irq, cntlr->channelNum); - return HDF_SUCCESS; + return HDF_ERR_INVALID_PARAM; } for (i = 0; i < cntlr->channelNum; i++) { channelStatus = cntlr->dmacGetChanStatus(cntlr, i); @@ -455,15 +452,19 @@ int DmacInit(struct DmaCntlr *cntlr) HDF_LOGE("check fail"); return HDF_FAILURE; } - if (cntlr->channelNum > DMAC_CHAN_NUM_MAX) { - HDF_LOGE("%s: invalid channel:%d", __func__, cntlr->channelNum); + if (cntlr->channelNum == 0 || cntlr->channelNum > DMAC_CHAN_NUM_MAX) { + HDF_LOGE("%s: invalid channel:%u", __func__, cntlr->channelNum); return HDF_FAILURE; } + if (cntlr->maxTransSize == 0) { + cntlr->maxTransSize = DMA_MAX_TRANS_SIZE_DEFAULT; + } cntlr->remapBase = (char *)OsalIoRemap((unsigned long)cntlr->phyBase, (unsigned long)cntlr->regSize); - OsalSpinInit(&cntlr->lock); + (void)OsalSpinInit(&cntlr->lock); cntlr->channelList = (struct DmacChanInfo *)OsalMemCalloc(sizeof(struct DmacChanInfo) * cntlr->channelNum); if (cntlr->channelList == NULL) { HDF_LOGE("channel list malloc fail"); + (void)OsalSpinDestroy(&cntlr->lock); OsalIoUnmap((void *)cntlr->remapBase); return HDF_FAILURE; } @@ -474,9 +475,10 @@ int DmacInit(struct DmaCntlr *cntlr) } ret = OsalRegisterIrq(cntlr->irq, 0, (OsalIRQHandle)DmacIsr, "PlatDmac", cntlr); if (ret != HDF_SUCCESS) { - HDF_LOGE("DMA Irq %d request failed, ret = %d\n", cntlr->irq, ret); + HDF_LOGE("DMA Irq %u request failed, ret = %d\n", cntlr->irq, ret); OsalMemFree(cntlr->channelList); cntlr->channelList = NULL; + (void)OsalSpinDestroy(&cntlr->lock); OsalIoUnmap((void *)cntlr->remapBase); } return ret; diff --git a/support/platform/src/emmc_core.c b/support/platform/src/emmc_core.c index b30cc433..91c0061c 100644 --- a/support/platform/src/emmc_core.c +++ b/support/platform/src/emmc_core.c @@ -6,8 +6,8 @@ * See the LICENSE file in the root of this repository for complete details. */ -#include "device_resource_if.h" #include "emmc_core.h" +#include "device_resource_if.h" #include "hdf_log.h" #include "osal_mem.h" @@ -16,11 +16,11 @@ int32_t EmmcCntlrFindHost(struct EmmcCntlr *cntlr) { if (cntlr == NULL || cntlr->method == NULL || cntlr->method->findHost == NULL) { - HDF_LOGE("EmmcCntlrFindHost: cntlr or method or findHost is NULL!"); + HDF_LOGE("EmmcCntlrFindHost: cntlr or method or findHost is null!"); return HDF_ERR_INVALID_PARAM; } if (cntlr->method->findHost(cntlr, &(cntlr->configData)) != HDF_SUCCESS) { - HDF_LOGE("EmmcCntlrFindHost: findHost fail!"); + HDF_LOGE("EmmcCntlrFindHost: findHost failed"); return HDF_ERR_INVALID_OBJECT; } return HDF_SUCCESS; @@ -42,8 +42,8 @@ int32_t EmmcCntlrGetCid(struct EmmcCntlr *cntlr, uint8_t *cid, uint32_t size) static int32_t EmmcGetCidWriteBackReply(struct HdfSBuf *reply, uint8_t *cid, uint32_t size) { - if (HdfSbufWriteBuffer(reply, cid, size) == false) { - HDF_LOGE("EmmcGetCidWriteBackReply: write to reply fail!"); + if (!HdfSbufWriteBuffer(reply, cid, size)) { + HDF_LOGE("EmmcGetCidWriteBackReply: write to reply failed"); return HDF_ERR_IO; } return HDF_SUCCESS; @@ -56,7 +56,7 @@ static int32_t EmmcGetCidDispatch(struct EmmcCntlr *cntlr, struct HdfSBuf *reply ret = EmmcCntlrGetCid(cntlr, cid, EMMC_CID_LEN); if (ret != HDF_SUCCESS) { - HDF_LOGE("EmmcGetCidDispatch: EmmcCntlrGetCid fail!"); + HDF_LOGE("EmmcGetCidDispatch: EmmcCntlrGetCid failed"); return ret; } return EmmcGetCidWriteBackReply(reply, cid, EMMC_CID_LEN); @@ -69,23 +69,23 @@ static int32_t EmmcIoDispatch(struct HdfDeviceIoClient *client, int cmd, struct (void)data; if (client == NULL || client->device == NULL) { - HDF_LOGE("EmmcIoDispatch: client or client->device is NULL"); + HDF_LOGE("EmmcIoDispatch: client or client->device is null"); return HDF_ERR_INVALID_OBJECT; } if (reply == NULL) { - HDF_LOGE("EmmcIoDispatch: reply is NULL"); + HDF_LOGE("EmmcIoDispatch: reply is null"); return HDF_ERR_INVALID_PARAM; } cntlr = (struct EmmcCntlr *)client->device->service; if (cntlr == NULL) { - HDF_LOGE("EmmcIoDispatch: service is NULL"); + HDF_LOGE("EmmcIoDispatch: service is null"); return HDF_ERR_INVALID_OBJECT; } if (cntlr->priv == NULL) { if (EmmcCntlrFindHost(cntlr) != HDF_SUCCESS) { - HDF_LOGE("EmmcIoDispatch: find host fail!"); + HDF_LOGE("EmmcIoDispatch: find host failed"); return HDF_ERR_INVALID_OBJECT; } } @@ -107,13 +107,13 @@ struct EmmcCntlr *EmmcCntlrCreateAndBind(struct HdfDeviceObject *device) struct EmmcCntlr *cntlr = NULL; if (device == NULL) { - HDF_LOGE("EmmcCntlrCreateAndBind: device is NULL!"); + HDF_LOGE("EmmcCntlrCreateAndBind: device is null!"); return NULL; } cntlr = (struct EmmcCntlr *)OsalMemCalloc(sizeof(*cntlr)); if (cntlr == NULL) { - HDF_LOGE("EmmcCntlrCreateAndBind: malloc host fail!"); + HDF_LOGE("EmmcCntlrCreateAndBind: malloc host failed"); return NULL; } cntlr->device = device; @@ -139,27 +139,27 @@ int32_t EmmcFillConfigData(struct HdfDeviceObject *device, struct EmmcConfigData int32_t ret; if (device == NULL || configData == NULL) { - HDF_LOGE("EmmcFillConfigData: input para is NULL."); + HDF_LOGE("EmmcFillConfigData: input para is null."); return HDF_FAILURE; } node = device->property; if (node == NULL) { - HDF_LOGE("EmmcFillConfigData: drs node is NULL."); + HDF_LOGE("EmmcFillConfigData: drs node is null."); return HDF_FAILURE; } drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); if (drsOps == NULL || drsOps->GetUint32 == NULL) { - HDF_LOGE("EmmcFillConfigData: invalid drs ops fail!"); + HDF_LOGE("EmmcFillConfigData: invalid drs ops failed"); return HDF_FAILURE; } ret = drsOps->GetUint32(node, "hostId", &(configData->hostId), 0); if (ret != HDF_SUCCESS) { - HDF_LOGE("EmmcFillConfigData: read funcNum fail!"); + HDF_LOGE("EmmcFillConfigData: read funcNum failed"); return ret; } - HDF_LOGD("EmmcFillConfigData: Success! hostId = %d.", configData->hostId); + HDF_LOGD("EmmcFillConfigData: Success! hostId = %u.", configData->hostId); return HDF_SUCCESS; } diff --git a/support/platform/src/emmc_if.c b/support/platform/src/emmc_if.c index 1010af75..ed70d88c 100644 --- a/support/platform/src/emmc_if.c +++ b/support/platform/src/emmc_if.c @@ -6,12 +6,12 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "emmc_if.h" #include #ifndef __USER__ #include "devsvc_manager_clnt.h" #include "emmc_core.h" #endif -#include "emmc_if.h" #include "hdf_base.h" #ifdef __USER__ #include "hdf_io_service_if.h" @@ -96,16 +96,10 @@ static int32_t EmmcGetCidReadReplyData(struct HdfSBuf *reply, uint8_t *cid, uint uint32_t rLen; const void *rBuf = NULL; - if (HdfSbufReadBuffer(reply, &rBuf, &rLen) == false) { + if (!HdfSbufReadBuffer(reply, &rBuf, &rLen)) { HDF_LOGE("EmmcGetCidReadReplyData: read rBuf fail!"); return HDF_ERR_IO; } - if (size != rLen) { - HDF_LOGE("EmmcGetCidReadReplyData: err len:%u, rLen:%u", size, rLen); - if (rLen > size) { - rLen = size; - } - } if (memcpy_s(cid, size, rBuf, rLen) != EOK) { HDF_LOGE("EmmcGetCidReadReplyData: memcpy rBuf fail!"); @@ -115,7 +109,7 @@ static int32_t EmmcGetCidReadReplyData(struct HdfSBuf *reply, uint8_t *cid, uint return HDF_SUCCESS; } -int32_t EmmcServiceGetCid(struct HdfIoService *service, uint8_t *cid, uint32_t size) +static int32_t EmmcServiceGetCid(struct HdfIoService *service, uint8_t *cid, uint32_t size) { int32_t ret; struct HdfSBuf *reply = NULL; @@ -161,7 +155,7 @@ int32_t EmmcGetCid(DevHandle handle, uint8_t *cid, uint32_t size) } if (cid == NULL || size < EMMC_CID_LEN) { - HDF_LOGE("EmmcGetCid: error parms!"); + HDF_LOGE("EmmcGetCid: error params!"); return HDF_ERR_INVALID_PARAM; } #ifdef __USER__ @@ -176,7 +170,7 @@ void EmmcGetHuid(uint8_t *cid, uint32_t size) DevHandle handle = NULL; if (cid == NULL || size == 0) { - HDF_LOGE("EmmcGetUdid: error parms!"); + HDF_LOGE("EmmcGetUdid: error params!"); return; } if (memset_s(cid, sizeof(uint8_t) * size, 0, sizeof(uint8_t) * size) != EOK) { @@ -186,11 +180,11 @@ void EmmcGetHuid(uint8_t *cid, uint32_t size) handle = EmmcOpen(0); if (handle == NULL) { - HDF_LOGD("EmmcGetUdid: open fail, use default value!"); + HDF_LOGW("EmmcGetUdid: open fail, use default value!"); return; } if (EmmcGetCid(handle, cid, size) != HDF_SUCCESS) { - HDF_LOGD("EmmcGetUdid: get fail, use default value!"); + HDF_LOGW("EmmcGetUdid: get fail, use default value!"); } EmmcClose(handle); } diff --git a/support/platform/src/i2c_if.c b/support/platform/src/i2c_if.c index 2da22446..59665074 100644 --- a/support/platform/src/i2c_if.c +++ b/support/platform/src/i2c_if.c @@ -267,7 +267,7 @@ int32_t I2cTransfer(DevHandle handle, struct I2cMsg *msgs, int16_t count) } if (msgs == NULL || count <= 0) { - HDF_LOGE("I2cTransfer: err parms! msgs:%s, count:%d", + HDF_LOGE("I2cTransfer: err params! msgs:%s, count:%d", (msgs == NULL) ? "0" : "x", count); return HDF_ERR_INVALID_PARAM; } diff --git a/support/platform/src/mipi_dsi_core.c b/support/platform/src/mipi_dsi_core.c index 0e2c74cb..6a616935 100644 --- a/support/platform/src/mipi_dsi_core.c +++ b/support/platform/src/mipi_dsi_core.c @@ -6,10 +6,10 @@ * See the LICENSE file in the root of this repository for complete details. */ -#include "osal_time.h" -#include "osal_mem.h" -#include "hdf_log.h" #include "mipi_dsi_core.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "osal_time.h" #define HDF_LOG_TAG mipi_dsi_core @@ -36,21 +36,21 @@ int32_t MipiDsiRegisterCntlr(struct MipiDsiCntlr *cntlr) return HDF_FAILURE; } -DevHandle MipiDsiOpen(uint8_t id) +DevHandle MipiDsiOpen(uint8_t number) { - if (id >= MAX_CNTLR_CNT) { - HDF_LOGE("id invalid"); + if (number >= MAX_CNTLR_CNT) { + HDF_LOGE("invalid number"); return NULL; } - if (g_mipiDsihandle[id].cntlr == NULL) { - HDF_LOGE("no mipi_dsi %d cntlr", id); + if (g_mipiDsihandle[number].cntlr == NULL) { + HDF_LOGE("no mipi_dsi %d cntlr", number); return NULL; } - if (OsalMutexLock(&(g_mipiDsihandle[id].lock)) != HDF_SUCCESS) { + if (OsalMutexLock(&(g_mipiDsihandle[number].lock)) != HDF_SUCCESS) { HDF_LOGE("mutex lock fail"); return NULL; } - return (DevHandle)(&(g_mipiDsihandle[id])); + return (DevHandle)(&(g_mipiDsihandle[number])); } void MipiDsiClose(DevHandle handle) @@ -64,7 +64,7 @@ void MipiDsiClose(DevHandle handle) static int32_t MipiDsiSetDevCfg(struct MipiDsiCntlr *cntlr) { - /* set controler config */ + /* set controller config */ if (cntlr->setCntlrCfg == NULL) { HDF_LOGE("setCntlrCfg is NULL"); return HDF_FAILURE; @@ -137,6 +137,7 @@ void MipiDsiSetLpMode(DevHandle handle) HDF_LOGI("toLp not support!"); } } + void MipiDsiSetHsMode(DevHandle handle) { struct MipiDsiCntlr *cntlr = NULL; @@ -151,6 +152,7 @@ void MipiDsiSetHsMode(DevHandle handle) HDF_LOGI("toHs not support!"); } } + void MipiDsiEnterUlps(DevHandle handle) { struct MipiDsiCntlr *cntlr = NULL; @@ -165,6 +167,7 @@ void MipiDsiEnterUlps(DevHandle handle) HDF_LOGI("enterUlps not support!"); } } + void MipiDsiExitUlps(DevHandle handle) { struct MipiDsiCntlr *cntlr = NULL; diff --git a/support/platform/src/rtc_base.c b/support/platform/src/rtc_base.c index 9b63c970..5e671ac0 100644 --- a/support/platform/src/rtc_base.c +++ b/support/platform/src/rtc_base.c @@ -6,9 +6,9 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "rtc_base.h" #include "hdf_log.h" #include "plat_log.h" -#include "rtc_base.h" #define HDF_LOG_TAG rtc_base @@ -21,7 +21,7 @@ uint8_t RtcGetMonthDays(const uint8_t isLeapYear, const uint8_t month) return 0; } - if (RTC_FEBRUARY == month) { + if (month == RTC_FEBRUARY) { days = RTC_TWO_MONTH_DAY + isLeapYear; } else { oddMonth = (month >= RTC_AUGUST) ? (month - RTC_UNIT_DIFF) : month; diff --git a/support/platform/src/rtc_core.c b/support/platform/src/rtc_core.c index 3df837d3..93ae2173 100644 --- a/support/platform/src/rtc_core.c +++ b/support/platform/src/rtc_core.c @@ -6,9 +6,9 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "rtc_core.h" #include "hdf_log.h" #include "osal_mem.h" -#include "rtc_core.h" #define HDF_LOG_TAG rtc_core diff --git a/support/platform/src/rtc_if.c b/support/platform/src/rtc_if.c index 232126ca..140f3c3f 100644 --- a/support/platform/src/rtc_if.c +++ b/support/platform/src/rtc_if.c @@ -6,13 +6,13 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "rtc_if.h" +#include "devsvc_manager_clnt.h" #include "hdf_base.h" #include "hdf_log.h" -#include "devsvc_manager_clnt.h" #include "osal_mem.h" #include "rtc_base.h" #include "rtc_core.h" -#include "rtc_if.h" #define HDF_LOG_TAG rtc_if diff --git a/support/platform/src/sdio_core.c b/support/platform/src/sdio_core.c index 990c460d..737480a9 100644 --- a/support/platform/src/sdio_core.c +++ b/support/platform/src/sdio_core.c @@ -6,10 +6,10 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "sdio_core.h" #include "device_resource_if.h" #include "osal_mem.h" #include "plat_log.h" -#include "sdio_core.h" #define HDF_LOG_TAG sdio_core diff --git a/support/platform/src/spi_if.c b/support/platform/src/spi_if.c index 45eb03af..4fb01a58 100644 --- a/support/platform/src/spi_if.c +++ b/support/platform/src/spi_if.c @@ -6,12 +6,12 @@ * See the LICENSE file in the root of this repository for complete details. */ -#include "securec.h" +#include "spi_if.h" #include "devsvc_manager_clnt.h" #include "hdf_log.h" #include "osal_mem.h" +#include "securec.h" #include "spi_core.h" -#include "spi_if.h" #define HDF_LOG_TAG spi_if #define HOST_NAME_LEN 32 @@ -128,17 +128,19 @@ DevHandle SpiOpen(const struct SpiDevInfo *info) return NULL; } - ret = SpiCntlrOpen(cntlr, info->csNum); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: SpiCntlrOpen error, ret is %d", __func__, ret); - return NULL; - } - object = (struct SpiObject *)OsalMemCalloc(sizeof(*object)); if (object == NULL) { HDF_LOGE("%s: object malloc error", __func__); return NULL; } + + ret = SpiCntlrOpen(cntlr, info->csNum); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: SpiCntlrOpen error, ret is %d", __func__, ret); + OsalMemFree(object); + return NULL; + } + object->cntlr = cntlr; object->csNum = info->csNum; return (DevHandle)object; diff --git a/support/platform/src/uart_core.c b/support/platform/src/uart_core.c index 524ad61f..71cfcb05 100644 --- a/support/platform/src/uart_core.c +++ b/support/platform/src/uart_core.c @@ -154,7 +154,7 @@ static int32_t UartUserSetTransMode(struct UartHost *host, struct HdfSBuf *data) size_t size; enum UartTransMode *mode = NULL; - if (!HdfSbufReadBuffer(data, (const void **)&mode, &size)) { + if (!HdfSbufReadBuffer(data, (const void **)&mode, &size) || mode == NULL) { HDF_LOGE("%s: sbuf read buffer failed", __func__); return HDF_ERR_IO; } diff --git a/support/platform/src/uart_if.c b/support/platform/src/uart_if.c index 88b1dccb..8ed38d0f 100644 --- a/support/platform/src/uart_if.c +++ b/support/platform/src/uart_if.c @@ -6,6 +6,7 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "uart_if.h" #include "securec.h" #ifndef __USER__ #include "devsvc_manager_clnt.h" @@ -17,7 +18,6 @@ #ifndef __USER__ #include "uart_core.h" #endif -#include "uart_if.h" #define HDF_LOG_TAG uart_if_c #define UART_HOST_NAME_LEN 32 From 3be68118ff01664d423b4775ec5938fb87eab768 Mon Sep 17 00:00:00 2001 From: zianed Date: Wed, 19 May 2021 23:40:11 +0800 Subject: [PATCH 16/21] modify word spell --- include/wifi/hdf_wifi_event.h | 10 +++++----- include/wifi/hdf_wifi_product.h | 2 +- include/wifi/net_device.h | 10 +++++----- include/wifi/wifi_inc.h | 2 +- include/wifi/wifi_mac80211_ops.h | 12 ++++++------ include/wifi/wifi_module.h | 2 +- model/network/wifi/platform/src/qos/flow_control.c | 8 ++++++-- model/sensor/driver/common/src/sensor_common.c | 2 +- model/sensor/driver/common/src/sensor_parser.c | 2 +- support/posix/src/osal_thread.c | 3 +-- .../config/hcs_parser/unittest/hcs_config_test.c | 2 +- 11 files changed, 29 insertions(+), 26 deletions(-) diff --git a/include/wifi/hdf_wifi_event.h b/include/wifi/hdf_wifi_event.h index a1c68fc8..cfae47b1 100644 --- a/include/wifi/hdf_wifi_event.h +++ b/include/wifi/hdf_wifi_event.h @@ -32,8 +32,8 @@ * @version 1.0 */ -#ifndef __HDF_WIFI_EVENT_H__ -#define __HDF_WIFI_EVENT_H__ +#ifndef HDF_WIFI_EVENT_H +#define HDF_WIFI_EVENT_H #include "hdf_wifi_cmd.h" #include "wifi_mac80211_ops.h" @@ -52,7 +52,7 @@ extern "C" { * @version 1.0 */ struct RateInfo { - uint8_t flags; /**< Flag field, used to indicate a specific rate transmission type of 802.11n */ + uint8_t flags; /**< Flag, used to indicate a specific rate transmission type of 802.11n */ uint8_t mcs; /**< Modulation and Coding Scheme (MCS) index of the HT/VHT/HE rate */ uint16_t legacy; /**< 100 kbit/s bit rate defined in 802.11a/b/g */ uint8_t nss; /**< Number of streams (for VHT and HE only) */ @@ -268,7 +268,7 @@ struct Ieee80211Mgmt { struct ScannedBssInfo { int32_t signal; /**< Signal strength */ int16_t freq; /**< Center frequency of the channel where the BSS is located */ - uint8_t arry[2]; /**< Reserved */ + uint8_t array[2]; /**< Reserved */ uint32_t mgmtLen; /**< Management frame length */ struct Ieee80211Mgmt *mgmt; /**< Start address of the management frame */ }; @@ -482,5 +482,5 @@ int32_t HdfWifiEventResetResult(const uint8_t chipId, int32_t resetStatus); #endif #endif -#endif /* __HDF_WIFI_EVENT_H__ */ +#endif /* HDF_WIFI_EVENT_H */ /** @} */ diff --git a/include/wifi/hdf_wifi_product.h b/include/wifi/hdf_wifi_product.h index 1007523c..40bf8842 100644 --- a/include/wifi/hdf_wifi_product.h +++ b/include/wifi/hdf_wifi_product.h @@ -113,7 +113,7 @@ struct WifiModule* HdfWlanGetModule(void); struct HdfWlanDevice *HdfWlanGetWlanDevice(uint8_t chipId); /** - * @brief Send broadcast event. + * @brief Sends a broadcast event. * * @param id Indicates the ID of the event to send. * @param data Indicates the pointer to the event information. diff --git a/include/wifi/net_device.h b/include/wifi/net_device.h index d13adb0f..9b1b5963 100644 --- a/include/wifi/net_device.h +++ b/include/wifi/net_device.h @@ -387,7 +387,7 @@ struct TcpHeader { uint16_t sPort; /**< Source port number */ uint16_t dPort; /**< Destination port number */ uint32_t seqNum; /**< Sequence number */ - uint32_t ackNum; /**< Acknowledgement number */ + uint32_t ackNum; /**< Acknowledgment number */ uint8_t offset; /**< Header length */ uint8_t flags; /**< Flags */ uint16_t window; /**< Window size */ @@ -465,7 +465,7 @@ typedef struct NetDevice { char name[IFNAMSIZ]; /**< Network device name {@link IFNAMSIZ} */ NetLinkType LinkLayerType; /**< Data link layer type */ IfType funType; /**< Network port type */ - char macAddr[MAC_ADDR_SIZE]; /**< MAC address {@link MAC_ADDR_SIZE} */ + unsigned char macAddr[MAC_ADDR_SIZE]; /**< MAC address {@link MAC_ADDR_SIZE} */ uint32_t flags; /**< Network port status */ uint32_t mtu; /**< Maximum transmission unit */ int32_t watchdogTime; /**< Watchdog duration */ @@ -496,12 +496,12 @@ struct NetDeviceInterFace { void (*deInit)(struct NetDevice *netDev); /**< Deinitializes a network device to be delete. */ int32_t (*open)(struct NetDevice *netDev); /**< Opens the data link layer. */ int32_t (*stop)(struct NetDevice *netDev); /**< Closes the data link layer. */ - NetDevTxResult (*xmit)(struct NetDevice *netDev, NetBuf *netBuff); /**< Sends data. */ + NetDevTxResult (*xmit)(struct NetDevice *netDev, NetBuf *netBuff); /**< Sends data. */ int32_t (*ioctl)(struct NetDevice *netDev, IfReq *req, int32_t cmd); /**< Used for the control command word. */ int32_t (*setMacAddr)(struct NetDevice *netDev, void *addr); /**< Sets the MAC address. */ struct NetDevStats *(*getStats)(struct NetDevice *netDev); /**< Obtains the statistics. */ void (*setNetIfStatus)(struct NetDevice *netDev, NetIfStatus status); /**< Sets the network port status. */ - uint16_t (*selectQueue)(struct NetDevice *netDev, NetBuf *netBuff);/**< Selects a priority queue. */ + uint16_t (*selectQueue)(struct NetDevice *netDev, NetBuf *netBuff); /**< Selects a priority queue. */ uint32_t (*netifNotify)(struct NetDevice *netDev, NetDevNotify *notify); /**< Notifies the network port status. */ int32_t (*changeMtu)(struct NetDevice *netDev, int32_t newMtu); /**< Changes the maximum number of * transmission units. @@ -658,7 +658,7 @@ int32_t NetIfSetAddr(const struct NetDevice *netDevice, const IpV4Addr *ipAddr, * @brief Notifies the network layer of the network port state. * * @param netDevice Indicates the pointer to the network device obtained during initialization. - * @paramstatus Indicates the network port state, as enumerated in {@link NetIfSatus}. + * @param status Indicates the network port state, as enumerated in {@link NetIfSatus}. * @param status Indicates the network port state, as enumerated in {@link NetIfSatus}. * * @return Returns 0 if the operation is successful; returns a non-zero value otherwise. diff --git a/include/wifi/wifi_inc.h b/include/wifi/wifi_inc.h index f1ec5336..5e25c080 100644 --- a/include/wifi/wifi_inc.h +++ b/include/wifi/wifi_inc.h @@ -62,7 +62,7 @@ struct BusDev; * @version 1.0 */ enum WifiMainFeatureType { - HDF_WIFI_FEATURE_AP, /**< AP */ + HDF_WIFI_FEATURE_AP, /**< Access point (AP) */ HDF_WIFI_FEATURE_STA, /**< Station */ HDF_WIFI_FEATURE_P2P, /**< Peer-to-peer (P2P) */ HDF_WIFI_FEATURE_NAN, /**< Neighbor Awareness Networking (NAN) */ diff --git a/include/wifi/wifi_mac80211_ops.h b/include/wifi/wifi_mac80211_ops.h index eb498f91..4e1244bf 100644 --- a/include/wifi/wifi_mac80211_ops.h +++ b/include/wifi/wifi_mac80211_ops.h @@ -32,8 +32,8 @@ * @version 1.0 */ -#ifndef _WIFI_MAC80211_OPS_H_ -#define _WIFI_MAC80211_OPS_H_ +#ifndef WIFI_MAC80211_OPS_H +#define WIFI_MAC80211_OPS_H #include "net_device.h" #include "hdf_wifi_cmd.h" @@ -440,9 +440,9 @@ struct WlanAPConf { struct WlanHwCapability { void (*Release)(struct WlanHwCapability *self); /**< Function for releasing the hardware capability */ struct WlanBand *bands[IEEE80211_NUM_BANDS]; /**< Frequency bands */ - uint16_t htCapability; /**< High-throughput (HT) capability */ - uint16_t supportedRateCount;/**< Number of supported rates */ - uint16_t *supportedRates; /**< An array of supported rates in 100 kbit/s */ + uint16_t htCapability; /**< High-throughput (HT) capability */ + uint16_t supportedRateCount; /**< Number of supported rates */ + uint16_t *supportedRates; /**< An array of supported rates in 100 kbit/s */ }; /** @@ -767,5 +767,5 @@ struct HdfMac80211APOps { int32_t (*GetAssociatedStasInfo)(NetDevice *netDev, WifiStaInfo *staInfo, uint32_t num); }; -#endif // _WIFI_MAC80211_OPS_H_ +#endif // WIFI_MAC80211_OPS_H /** @} */ diff --git a/include/wifi/wifi_module.h b/include/wifi/wifi_module.h index f58b04dd..6bb836c2 100644 --- a/include/wifi/wifi_module.h +++ b/include/wifi/wifi_module.h @@ -206,7 +206,7 @@ int16_t InitWifiModule(struct WifiModule *module, const struct HdfConfigWlanModu #define RETURN_IF_CHIPOPS_NOT_IMPLEMENT(chipOps, opsName) \ do { \ - if ((chipOps) == NULL ||(chipOps)->opsName == NULL) { \ + if ((chipOps) == NULL || (chipOps)->opsName == NULL) { \ HDF_LOGE("macOps" #opsName "not implement"); \ return HDF_ERR_INVALID_OBJECT; \ } \ diff --git a/model/network/wifi/platform/src/qos/flow_control.c b/model/network/wifi/platform/src/qos/flow_control.c index 923598eb..b4963f5c 100644 --- a/model/network/wifi/platform/src/qos/flow_control.c +++ b/model/network/wifi/platform/src/qos/flow_control.c @@ -101,7 +101,7 @@ static FlowControlQueueID IpProcessFunc(const void *buff, uint32_t len) return QUEUE_ID_COUNT; } if (len < sizeof(struct IpHeader)) { - HDF_LOGE("%s fail: len not right!", __func__); + HDF_LOGE("%s fail: IpHeader len not right!", __func__); return QUEUE_ID_COUNT; } ipHeader = (struct IpHeader *)buff; @@ -116,6 +116,10 @@ static FlowControlQueueID IpProcessFunc(const void *buff, uint32_t len) * ---------------------------------------------------------------------- */ id = TosToFcQueueId(ipHeader->tos >> IP_PRI_SHIFT); + if ((len - sizeof(struct IpHeader)) < sizeof(struct UdpHeader)) { + HDF_LOGE("%s fail: UdpHeader len not right!", __func__); + return QUEUE_ID_COUNT; + } udpHdr = (struct UdpHeader *)(ipHeader + 1); if (((ntohs(ipHeader->fragInfo) & 0x1FFF) == 0) && IsDhcpPort(udpHdr, len - sizeof(struct IpHeader))) { id = VIP_QUEUE_ID; @@ -381,7 +385,7 @@ void DeInitFlowControl(struct FlowControlModule *fcm) return; } - /* 1:Detroy task. 2:Destroy osalwait. 3:free NetBuff. */ + /* 1:Destroy task. 2:Destroy osalwait. 3:free NetBuff. */ DestroyFlowControlTask(fcm); for (i = 0; i < FLOW_DIR_COUNT; i++) { OsalSemDestroy(&fcm->sem[i]); diff --git a/model/sensor/driver/common/src/sensor_common.c b/model/sensor/driver/common/src/sensor_common.c index a48719f9..c7130f67 100644 --- a/model/sensor/driver/common/src/sensor_common.c +++ b/model/sensor/driver/common/src/sensor_common.c @@ -160,4 +160,4 @@ void DestroySensorThread(struct OsalThread *thread, uint8_t *status) OsalThreadDestroy(thread); *status = SENSOR_THREAD_DESTROY; -} +} \ No newline at end of file diff --git a/model/sensor/driver/common/src/sensor_parser.c b/model/sensor/driver/common/src/sensor_parser.c index 0030fc48..57472baa 100644 --- a/model/sensor/driver/common/src/sensor_parser.c +++ b/model/sensor/driver/common/src/sensor_parser.c @@ -379,4 +379,4 @@ int32_t GetSensorBaseConfigData(const struct DeviceResourceNode *node, struct Se CHECK_PARSER_RESULT_RETURN_VALUE(ret, "accelAttr"); return HDF_SUCCESS; -} +} \ No newline at end of file diff --git a/support/posix/src/osal_thread.c b/support/posix/src/osal_thread.c index 4fcfce15..12c162ff 100644 --- a/support/posix/src/osal_thread.c +++ b/support/posix/src/osal_thread.c @@ -11,7 +11,6 @@ #include "hdf_base.h" #include "hdf_log.h" #include "osal_mem.h" - #ifndef PTHREAD_STACK_MIN #define OSAL_PTHREAD_STACK_MIN 4096 #else @@ -79,7 +78,7 @@ int32_t OsalThreadCreate(struct OsalThread *thread, OsalThreadEntry threadEntry, int32_t OsalThreadDestroy(struct OsalThread *thread) { - if (thread->realThread != NULL) { + if (thread != NULL && thread->realThread != NULL) { OsalMemFree(thread->realThread); thread->realThread = NULL; } diff --git a/test/unittest/ability/config/hcs_parser/unittest/hcs_config_test.c b/test/unittest/ability/config/hcs_parser/unittest/hcs_config_test.c index cb2ea0c1..b5757268 100644 --- a/test/unittest/ability/config/hcs_parser/unittest/hcs_config_test.c +++ b/test/unittest/ability/config/hcs_parser/unittest/hcs_config_test.c @@ -1019,4 +1019,4 @@ int HcsTestGetNodeAttrRefFail(void) return HDF_FAILURE; } return HDF_SUCCESS; -} +} \ No newline at end of file From 912c7aab55ed8a8969991c5ad72b56a087b590a4 Mon Sep 17 00:00:00 2001 From: yuanbo Date: Thu, 20 May 2021 08:47:45 +0800 Subject: [PATCH 17/21] fix spellcheck issue --- ability/sbuf/include/hdf_sbuf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ability/sbuf/include/hdf_sbuf.h b/ability/sbuf/include/hdf_sbuf.h index cb6e1f41..29ed7006 100644 --- a/ability/sbuf/include/hdf_sbuf.h +++ b/ability/sbuf/include/hdf_sbuf.h @@ -9,7 +9,7 @@ * @addtogroup Core * @{ * - * @brief Provides functions to use the OpenHarmonyOS Driver Foundation (HDF). + * @brief Provides functions to use the OpenHarmony Driver Foundation (HDF). * * The HDF implements driver framework capabilities such as driver loading, service management, driver message model, * and power management. From 95e8c341427f3d86c1349481e3918617172cca3d Mon Sep 17 00:00:00 2001 From: haizhouyang Date: Thu, 20 May 2021 12:45:17 +0800 Subject: [PATCH 18/21] replace apache by dual license --- support/posix/src/osal_spinlock.c | 13 +++---------- utils/src/hdf_thread_ex.c | 13 +++---------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/support/posix/src/osal_spinlock.c b/support/posix/src/osal_spinlock.c index 695623b8..e51b7ff9 100644 --- a/support/posix/src/osal_spinlock.c +++ b/support/posix/src/osal_spinlock.c @@ -1,16 +1,9 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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 "osal_spinlock.h" diff --git a/utils/src/hdf_thread_ex.c b/utils/src/hdf_thread_ex.c index ca0f1548..c4e1edea 100644 --- a/utils/src/hdf_thread_ex.c +++ b/utils/src/hdf_thread_ex.c @@ -1,16 +1,9 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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_thread_ex.h" From 3814d9451862a2335c19dd0362a7c49f0f98fc8d Mon Sep 17 00:00:00 2001 From: haizhouyang Date: Thu, 20 May 2021 14:24:29 +0800 Subject: [PATCH 19/21] sync some bugfix from l2 --- support/platform/src/i2c_core.c | 4 ++-- support/platform/test/unittest/common/hdf_emmc_test.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/support/platform/src/i2c_core.c b/support/platform/src/i2c_core.c index 815e43c4..93b6e40f 100644 --- a/support/platform/src/i2c_core.c +++ b/support/platform/src/i2c_core.c @@ -107,7 +107,7 @@ static void I2cManagerRemoveCntlr(struct I2cCntlr *cntlr) } /* - * Find an i2c cntroller by bus number, without ref count + * Find an i2c controller by bus number, without ref count */ static struct I2cCntlr *I2cManagerFindCntlr(int16_t number) { @@ -236,7 +236,7 @@ static int32_t I2cTransferRebuildMsgs(struct HdfSBuf *data, struct I2cMsg **ppms uint8_t *bufReply = NULL; struct I2cMsg *msgs = NULL; - if (!HdfSbufReadBuffer(data, (const void **)&msgs, &len)) { + if (!HdfSbufReadBuffer(data, (const void **)&msgs, &len) || msgs == NULL) { HDF_LOGE("I2cTransferRebuildMsgs: read msgs fail!"); return HDF_ERR_IO; } diff --git a/support/platform/test/unittest/common/hdf_emmc_test.cpp b/support/platform/test/unittest/common/hdf_emmc_test.cpp index 9e1b51dd..ab10b066 100644 --- a/support/platform/test/unittest/common/hdf_emmc_test.cpp +++ b/support/platform/test/unittest/common/hdf_emmc_test.cpp @@ -56,7 +56,7 @@ static void TestUserEmmcGetCid(void) EmmcGetHuid(cid, EMMC_CID_LEN); for (i = 0; i < EMMC_CID_LEN; i++) { - printf("user interface get cid[%d] = 0x%x\n", i, cid[i]); + printf("user interface get cid[%u] = 0x%x\n", i, cid[i]); } } From d7810c447f719319769818d06a0416805755ce28 Mon Sep 17 00:00:00 2001 From: zianed Date: Thu, 20 May 2021 16:37:37 +0800 Subject: [PATCH 20/21] keep binary --- .gitattributes | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index e69de29b..00000000 From 25c3076d82c887cfebf695721892f480d313f62c Mon Sep 17 00:00:00 2001 From: YOUR_NAME Date: Thu, 20 May 2021 13:35:58 +0000 Subject: [PATCH 21/21] =?UTF-8?q?IssueNo=EF=BC=9A#I3S732=20Description:syn?= =?UTF-8?q?c=20L2=20input=20and=20display=20to=20L1=20Feature=20or=20Bugfi?= =?UTF-8?q?x:Bugfix=20Binary=20Source:=20No?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- model/display/driver/hdf_disp.c | 307 ++++++++++++------ model/display/driver/hdf_disp.h | 11 +- model/display/driver/hi35xx_disp.c | 13 +- model/display/driver/lcd_abs_if.c | 18 +- model/display/driver/lcd_abs_if.h | 17 +- .../driver/lcdkit/lcdkit_parse_config.c | 11 +- model/display/driver/lcdkit/lite_lcdkit.c | 8 +- model/display/driver/panel/mipi_icn9700.c | 24 +- model/display/driver/panel/ssp_st7789.c | 8 +- model/display/driver/panel/ssp_st7789.h | 1 - model/input/driver/event_hub.c | 6 + model/input/driver/hdf_hid.c | 48 --- model/input/driver/hdf_hid_adapter.c | 164 ++++++++++ model/input/driver/hdf_hid_adapter.h | 27 ++ model/input/driver/hdf_input_device_manager.c | 141 ++++++-- model/input/driver/hdf_input_device_manager.h | 35 +- model/input/driver/hdf_key.c | 15 +- model/input/driver/hdf_touch.c | 66 ++-- model/input/driver/hdf_touch.h | 1 + model/input/driver/input_config_parser.c | 8 +- model/input/driver/touchscreen/touch_ft6336.c | 4 +- model/input/driver/touchscreen/touch_gt911.c | 22 +- model/input/driver/touchscreen/touch_gt911.h | 31 +- 23 files changed, 719 insertions(+), 267 deletions(-) delete mode 100755 model/input/driver/hdf_hid.c create mode 100644 model/input/driver/hdf_hid_adapter.c create mode 100644 model/input/driver/hdf_hid_adapter.h diff --git a/model/display/driver/hdf_disp.c b/model/display/driver/hdf_disp.c index 910d5ffe..49470eb9 100644 --- a/model/display/driver/hdf_disp.c +++ b/model/display/driver/hdf_disp.c @@ -13,133 +13,141 @@ #define OFFSET_TWO_BYTE 16 -struct DispOperations *g_dispOps = NULL; +static struct PlatformOps *g_platformOps = NULL; -int32_t DispRegister(struct DispOperations *ops) +int32_t PlatformRegister(struct PlatformOps *ops) { - if (g_dispOps == NULL) { - g_dispOps = ops; + if (g_platformOps == NULL) { + g_platformOps = ops; HDF_LOGI("%s: disp ops register success", __func__); return HDF_SUCCESS; } - HDF_LOGD("%s: disp ops registered", __func__); + HDF_LOGD("%s: success", __func__); return HDF_FAILURE; } +static struct PlatformOps *GetPlatformOps(void) +{ + return g_platformOps; +} + +static int32_t InitDisp(uint32_t devId); +static int32_t DispOn(uint32_t devId); +static int32_t DispOff(uint32_t devId); +static int32_t SetDispBacklight(uint32_t devId, uint32_t level); +static int32_t GetDispInfo(uint32_t devId, struct DispInfo *info); + struct DispOperations *GetDispOps(void) { - return g_dispOps; + static struct DispOperations dispOps = { + .init = InitDisp, + .on = DispOn, + .off = DispOff, + .setBacklight = SetDispBacklight, + .getDispInfo = GetDispInfo, + }; + return &dispOps; +} + +#ifdef __KERNEL__ +EXPORT_SYMBOL(GetDispOps); +#endif + +static int32_t InitDisp(uint32_t devId) +{ + return 0; } static int32_t DispOn(uint32_t devId) { - int32_t ret; - struct DispOperations *ops = NULL; + int32_t ret = HDF_FAILURE; + struct PlatformOps *ops = NULL; - ops = GetDispOps(); - if (ops == NULL) { - HDF_LOGE("%s: ops is null", __func__); - return HDF_FAILURE; - } - if (ops->on != NULL) { + ops = GetPlatformOps(); + if (ops && ops->on) { ret = ops->on(devId); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: ops on failed", __func__); - return HDF_FAILURE; - } } - return HDF_SUCCESS; + return ret; } static int32_t DispOff(uint32_t devId) { - int32_t ret; - struct DispOperations *ops = NULL; + int32_t ret = HDF_FAILURE; + struct PlatformOps *ops = NULL; - ops = GetDispOps(); - if (ops == NULL) { - HDF_LOGE("%s: ops is null", __func__); - return HDF_FAILURE; - } - if (ops->off != NULL) { + ops = GetPlatformOps(); + if (ops && ops->off) { ret = ops->off(devId); + } + return ret; +} + +static int32_t SetDispBacklight(uint32_t devId, uint32_t level) +{ + int32_t ret = HDF_FAILURE; + struct PanelStatus *panelStatus = NULL; + + struct PanelInfo *info = GetPanelInfo(devId); + if (info == NULL) { + HDF_LOGE("%s:GetPanelInfo failed", __func__); + return HDF_FAILURE; + } + if (level > info->blk.maxLevel) { + level = info->blk.maxLevel; + } else if (level < info->blk.minLevel && level != 0) { + level = info->blk.minLevel; + } + struct PlatformOps *ops = GetPlatformOps(); + if (ops == NULL) { + HDF_LOGE("%s: ops is null", __func__); + return HDF_FAILURE; + } + if (ops->setBacklight != NULL) { + ret = ops->setBacklight(devId, level); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: ops off failed", __func__); + HDF_LOGE("%s: setBacklight failed", __func__); return HDF_FAILURE; } } + if (ret == HDF_SUCCESS) { + panelStatus = GetPanelStatus(devId); + if (!panelStatus) { + HDF_LOGE("%s: panelStatus is null", __func__); + return HDF_FAILURE; + } + panelStatus->currLevel = level; + } + HDF_LOGI("%s:level = %u", __func__, level); return HDF_SUCCESS; } -static int32_t DispInit(struct HdfDeviceObject *device, struct HdfSBuf *reqData, struct HdfSBuf *rspData) +static int32_t GetDispInfo(uint32_t devId, struct DispInfo *info) { - (void)device; - (void)rspData; - int32_t ret; - uint32_t devId = 0; + struct PlatformOps *ops = NULL; - if (reqData == NULL) { - return HDF_ERR_INVALID_PARAM; - } - if (!HdfSbufReadUint32(reqData, &devId)) { - HDF_LOGE("%s: HdfSbufReadBuffer failed", __func__); + if (info == NULL) { + HDF_LOGE("%s:info is null", __func__); return HDF_FAILURE; } - - struct DispOperations *ops = NULL; - ops = GetDispOps(); + ops = GetPlatformOps(); if (ops == NULL) { HDF_LOGE("%s: ops is null", __func__); return HDF_FAILURE; } - if (ops->init != NULL) { - ret = ops->init(devId); - if (ret) { - HDF_LOGE("%s: init failed", __func__); - return HDF_FAILURE; - } - } - return HDF_SUCCESS; -} - -static int32_t GetDispInfo(struct HdfDeviceObject *device, struct HdfSBuf *reqData, struct HdfSBuf *rspData) -{ - (void)device; - (void)rspData; - uint32_t devId = 0; - struct DispInfo info; - struct DispOperations *ops = NULL; - - if (reqData == NULL) { - return HDF_ERR_INVALID_PARAM; - } - if (!HdfSbufReadUint32(reqData, &devId)) { - HDF_LOGE("%s: HdfSbufReadBuffer failed", __func__); - return HDF_FAILURE; - } - - ops = GetDispOps(); - if (ops == NULL) { - HDF_LOGE("%s: ops is null", __func__); - return HDF_FAILURE; - } - (void)memset_s(&info, sizeof(struct DispInfo), 0, sizeof(struct DispInfo)); if (ops->getDispInfo != NULL) { - if (ops->getDispInfo(devId, &info)) { + if (ops->getDispInfo(devId, info)) { HDF_LOGE("%s: getDispInfo failed", __func__); return HDF_FAILURE; } } - if (!HdfSbufWriteBuffer(rspData, &info, sizeof(struct DispInfo)) != 0) { - HDF_LOGE("%s: copy info failed", __func__); - return HDF_FAILURE; - } return HDF_SUCCESS; } -static int32_t SetPowerMode(struct HdfDeviceObject *device, struct HdfSBuf *reqData, struct HdfSBuf *rspData) +static int32_t SetPowerStatus(struct HdfDeviceObject *device, struct HdfSBuf *reqData, struct HdfSBuf *rspData) { uint32_t para = 0; + int32_t ret = HDF_FAILURE; + struct PanelStatus *panelStatus = NULL; (void)device; (void)rspData; @@ -151,20 +159,58 @@ static int32_t SetPowerMode(struct HdfDeviceObject *device, struct HdfSBuf *reqD return HDF_FAILURE; } uint32_t devId = (para >> OFFSET_TWO_BYTE) & 0xffff; - uint32_t mode = para & 0xffff; - if (mode == DISP_ON) { - return DispOn(devId); + uint32_t powerStatus = para & 0xffff; + switch (powerStatus) { + case POWER_STATUS_ON: + ret = DispOn(devId); + break; + case POWER_STATUS_OFF: + ret = DispOff(devId); + break; + default: + HDF_LOGE("%s: not support powerStatus: %d", __func__, powerStatus); + break; } - if (mode == DISP_OFF) { - return DispOff(devId); + if (ret == HDF_SUCCESS) { + panelStatus = GetPanelStatus(devId); + if (panelStatus == NULL) { + HDF_LOGE("%s: panelStatus is null", __func__); + return HDF_FAILURE; + } + panelStatus->powerStatus = powerStatus; } - HDF_LOGE("not support mode:%u", mode); - return HDF_FAILURE; + return ret; +} + +static int32_t GetPowerStatus(struct HdfDeviceObject *device, struct HdfSBuf *reqData, struct HdfSBuf *rspData) +{ + uint32_t devId = 0; + struct PanelStatus *panelStatus = NULL; + + (void)device; + if (reqData == NULL) { + return HDF_ERR_INVALID_PARAM; + } + if (!HdfSbufReadUint32(reqData, &devId)) { + HDF_LOGE("%s: HdfSbufReadBuffer failed", __func__); + return HDF_FAILURE; + } + panelStatus = GetPanelStatus(devId); + if (!panelStatus) { + HDF_LOGE("%s: panelStatus is null", __func__); + return HDF_FAILURE; + } + if (!HdfSbufWriteUint32(rspData, panelStatus->powerStatus)) { + HDF_LOGE("%s: HdfSbufWriteUint32 failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; } static int32_t SetBacklight(struct HdfDeviceObject *device, struct HdfSBuf *reqData, struct HdfSBuf *rspData) { int32_t ret; + (void)device; (void)rspData; if (reqData == NULL) { @@ -177,37 +223,67 @@ static int32_t SetBacklight(struct HdfDeviceObject *device, struct HdfSBuf *reqD } uint32_t devId = (para >> OFFSET_TWO_BYTE) & 0xffff; uint32_t level = para & 0xffff; - struct PanelInfo *info = GetPanelInfo(devId); - if (info == NULL) { - HDF_LOGE("%s:GetPanelInfo failed", __func__); + ret = SetDispBacklight(devId, level); + return ret; +} + +static int32_t GetBacklight(struct HdfDeviceObject *device, struct HdfSBuf *reqData, struct HdfSBuf *rspData) +{ + uint32_t devId = 0; + struct PanelStatus *panelStatus = NULL; + + (void)device; + if (reqData == NULL) { + return HDF_ERR_INVALID_PARAM; + } + if (!HdfSbufReadUint32(reqData, &devId)) { + HDF_LOGE("%s: HdfSbufReadBuffer failed", __func__); return HDF_FAILURE; } - if (level > info->blk.maxLevel) { - level = info->blk.maxLevel; - } else if (level < info->blk.minLevel && level != 0) { - level = info->blk.minLevel; - } - struct DispOperations *ops = GetDispOps(); - if (ops == NULL) { - HDF_LOGE("%s: ops is null", __func__); + panelStatus = GetPanelStatus(devId); + if (!panelStatus) { + HDF_LOGE("%s: panelStatus is null", __func__); return HDF_FAILURE; } - if (ops->setBacklight != NULL) { - ret = ops->setBacklight(devId, level); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: setBacklight failed", __func__); - return HDF_FAILURE; - } + if (!HdfSbufWriteUint32(rspData, panelStatus->currLevel)) { + HDF_LOGE("%s: HdfSbufWriteUint32 failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t GetInfo(struct HdfDeviceObject *device, struct HdfSBuf *reqData, struct HdfSBuf *rspData) +{ + (void)device; + (void)rspData; + uint32_t devId = 0; + struct DispInfo info; + + if (reqData == NULL) { + return HDF_ERR_INVALID_PARAM; + } + if (!HdfSbufReadUint32(reqData, &devId)) { + HDF_LOGE("%s: HdfSbufReadBuffer failed", __func__); + return HDF_FAILURE; + } + (void)memset_s(&info, sizeof(struct DispInfo), 0, sizeof(struct DispInfo)); + if (GetDispInfo(devId, &info) != HDF_SUCCESS) { + HDF_LOGE("%s: GetDispInfo failed", __func__); + return HDF_FAILURE; + } + if (!HdfSbufWriteBuffer(rspData, &info, sizeof(struct DispInfo)) != 0) { + HDF_LOGE("%s: copy info failed", __func__); + return HDF_FAILURE; } - HDF_LOGI("%s:level = %u", __func__, level); return HDF_SUCCESS; } DispCmdHandle g_dispCmdHandle[] = { - DispInit, - GetDispInfo, - SetPowerMode, + GetPowerStatus, + GetInfo, + SetPowerStatus, SetBacklight, + GetBacklight, }; static int32_t DispCmdProcess(struct HdfDeviceObject *device, int32_t cmd, struct HdfSBuf *reqData, @@ -253,10 +329,27 @@ static int HdfDispBind(struct HdfDeviceObject *dev) static int32_t HdfDispEntryInit(struct HdfDeviceObject *object) { + int32_t ret; + int32_t i; + struct PlatformOps *ops = GetPlatformOps(); + if (object == NULL) { HDF_LOGE("%s: object is null!", __func__); return HDF_FAILURE; } + if (ops == NULL) { + HDF_LOGE("%s: ops is null", __func__); + return HDF_FAILURE; + } + if (ops->init != NULL) { + for (i = 0; i < g_numRegisteredPanel; i++) { + ret = ops->init(i); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: init failed", __func__); + return HDF_FAILURE; + } + } + } return HDF_SUCCESS; } diff --git a/model/display/driver/hdf_disp.h b/model/display/driver/hdf_disp.h index c2acd9a4..7a8a5015 100644 --- a/model/display/driver/hdf_disp.h +++ b/model/display/driver/hdf_disp.h @@ -45,11 +45,20 @@ struct DispOperations { int32_t (*getDispInfo)(uint32_t devId, struct DispInfo *info); }; +struct PlatformOps { + int32_t (*init)(uint32_t devId); + int32_t (*on)(uint32_t devId); + int32_t (*off)(uint32_t devId); + int32_t (*setBacklight)(uint32_t devId, uint32_t level); + int32_t (*getDispInfo)(uint32_t devId, struct DispInfo *info); +}; + enum PowerMode { DISP_ON, DISP_OFF, }; -int32_t DispRegister(struct DispOperations *ops); +int32_t PlatformRegister(struct PlatformOps *ops); struct PanelInfo *GetPanelInfo(int32_t index); +struct PanelStatus *GetPanelStatus(int32_t index); #endif /* HDF_DISP_H */ diff --git a/model/display/driver/hi35xx_disp.c b/model/display/driver/hi35xx_disp.c index 18a31425..44665b15 100644 --- a/model/display/driver/hi35xx_disp.c +++ b/model/display/driver/hi35xx_disp.c @@ -6,6 +6,7 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "hi35xx_disp.h" #include #include "hdf_base.h" #include "hdf_device_desc.h" @@ -14,7 +15,6 @@ #include "lcd_abs_if.h" #include "osal_io.h" #include "pwm_if.h" -#include "hi35xx_disp.h" #define TRANSFORM_KILO 1000 #define TRANSFORM_MILL 1000000 @@ -186,10 +186,13 @@ static uint32_t CalcDataRate(struct PanelInfo *info) } else { bitClk = bitNum / TRANSFORM_MILL + 1; } + if (!info->mipi.lane) { + return HDF_FAILURE; + } if ((bitClk % info->mipi.lane) == 0) { return bitClk / info->mipi.lane; } - return bitClk / info->mipi.lane + 1; + return (bitClk / info->mipi.lane) + 1; } static int32_t MipiDsiInit(struct PanelInfo *info) @@ -225,7 +228,7 @@ static int32_t MipiDsiInit(struct PanelInfo *info) HDF_LOGE("%s:MipiDsiSetCfg failed", __func__); } MipiDsiClose(mipiHandle); - HDF_LOGI("%s:pixelClk = %d, phyDataRate = %d", __func__, cfg.pixelClk, cfg.phyDataRate); + HDF_LOGI("%s:pixelClk = %d, phyDataRate = %u", __func__, cfg.pixelClk, cfg.phyDataRate); return ret; } @@ -425,7 +428,7 @@ static int32_t Hi35xxSetBacklight(uint32_t devId, uint32_t level) return HDF_SUCCESS; } -struct DispOperations g_hi35xxOps = { +struct PlatformOps g_hi35xxOps = { .init = Hi35xxInit, .on = Hi35xxOn, .off = Hi35xxOff, @@ -439,7 +442,7 @@ static int32_t Hi35xxEntryInit(struct HdfDeviceObject *object) HDF_LOGE("%s: param is null!", __func__); return HDF_FAILURE; } - return DispRegister(&g_hi35xxOps); + return PlatformRegister(&g_hi35xxOps); } struct HdfDriverEntry g_hi35xxDevEntry = { diff --git a/model/display/driver/lcd_abs_if.c b/model/display/driver/lcd_abs_if.c index d414c216..c95d2e50 100644 --- a/model/display/driver/lcd_abs_if.c +++ b/model/display/driver/lcd_abs_if.c @@ -6,15 +6,15 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "lcd_abs_if.h" #include #include "hdf_device_desc.h" #include "osal.h" -#include "lcd_abs_if.h" /* support max panel number */ #define PANEL_MAX 2 static struct PanelData *g_panelData[PANEL_MAX]; -static int32_t numRegisteredPanel; +int32_t g_numRegisteredPanel; int32_t PanelDataRegister(struct PanelData *data) { @@ -24,10 +24,10 @@ int32_t PanelDataRegister(struct PanelData *data) HDF_LOGE("%s: panel data is null", __func__); return HDF_ERR_INVALID_PARAM; } - if (numRegisteredPanel == PANEL_MAX) { + if (g_numRegisteredPanel == PANEL_MAX) { return HDF_FAILURE; } - numRegisteredPanel++; + g_numRegisteredPanel++; for (i = 0; i < PANEL_MAX; i++) { if (g_panelData[i] == NULL) { break; @@ -60,3 +60,13 @@ struct PanelInfo *GetPanelInfo(int32_t index) return g_panelData[index]->info; } +struct PanelStatus *GetPanelStatus(const int32_t index) +{ + if ((index >= PANEL_MAX) || index < 0) { + return NULL; + } + if (g_panelData[index] == NULL) { + return NULL; + } + return g_panelData[index]->status; +} diff --git a/model/display/driver/lcd_abs_if.h b/model/display/driver/lcd_abs_if.h index e35ce204..04ed31ae 100644 --- a/model/display/driver/lcd_abs_if.h +++ b/model/display/driver/lcd_abs_if.h @@ -26,7 +26,7 @@ enum BacklightType { BLK_MIPI, }; -/* output timming */ +/* output timing */ enum IntfSync { OUTPUT_USER = 0, /* User timing */ OUTPUT_PAL, /* PAL standard */ @@ -85,6 +85,14 @@ struct MipiDsiDesc { enum DsiOutFormat format; }; +enum PowerStatus { + POWER_STATUS_ON, /* The power status is on */ + POWER_STATUS_STANDBY, /* The power status is standby */ + POWER_STATUS_SUSPEND, /* The power status is suspend */ + POWER_STATUS_OFF, /* The power status is off */ + POWER_STATUS_BUTT +}; + struct BlkDesc { uint32_t type; uint32_t minLevel; @@ -114,14 +122,21 @@ struct PanelInfo { struct PwmCfg pwm; }; +struct PanelStatus { + enum PowerStatus powerStatus; + uint32_t currLevel; +}; struct PanelData { struct PanelInfo *info; + struct PanelStatus *status; int32_t (*init)(void); int32_t (*on)(void); int32_t (*off)(void); int32_t (*setBacklight)(uint32_t level); }; +extern int32_t g_numRegisteredPanel; + int32_t PanelDataRegister(struct PanelData *data); #endif /* LCD_ABS_IF_H */ diff --git a/model/display/driver/lcdkit/lcdkit_parse_config.c b/model/display/driver/lcdkit/lcdkit_parse_config.c index 89a66d49..64c3d3b8 100644 --- a/model/display/driver/lcdkit/lcdkit_parse_config.c +++ b/model/display/driver/lcdkit/lcdkit_parse_config.c @@ -45,6 +45,8 @@ static int32_t ParseDsiCmd(struct PanelCmd *cmd, int32_t count, uint8_t *array, return HDF_FAILURE; } int32_t ret; + int32_t i; + int32_t num = 0; cmd->count = count; cmd->dsiCmd = dsiCmd; uint8_t *tmpArray = array; @@ -56,6 +58,9 @@ static int32_t ParseDsiCmd(struct PanelCmd *cmd, int32_t count, uint8_t *array, tmpCmd->payload = (uint8_t *)OsalMemCalloc(tmpCmd->dataLen * sizeof(uint8_t)); if (tmpCmd->payload == NULL) { HDF_LOGE("%s: OsalMemCalloc failed", __func__); + for (i = 0; i < num; i++) { + OsalMemFree(dsiCmd[i]->payload); + } OsalMemFree(array); OsalMemFree(dsiCmd); cmd->dsiCmd = NULL; @@ -63,9 +68,12 @@ static int32_t ParseDsiCmd(struct PanelCmd *cmd, int32_t count, uint8_t *array, return HDF_FAILURE; } - ret = memcpy_s(tmpCmd->payload, tmpCmd->dataLen, &tmpArray[DSI_CMD_HEAD], tmpCmd->dataLen); + ret = memcpy_s(tmpCmd->payload, tmpCmd->dataLen, &tmpArray[DSI_CMD_HEAD], DSI_CMD_HEAD); if (ret != EOK) { HDF_LOGE("%s: memcpy_s failed, ret %d", __func__, ret); + for (i = 0; i < num; i++) { + OsalMemFree(dsiCmd[i]->payload); + } OsalMemFree(array); OsalMemFree(dsiCmd); cmd->dsiCmd = NULL; @@ -76,6 +84,7 @@ static int32_t ParseDsiCmd(struct PanelCmd *cmd, int32_t count, uint8_t *array, tmpArray += DSI_CMD_HEAD + tmpCmd->dataLen; tmpCmd++; count--; + num++; len -= DSI_CMD_HEAD + tmpCmd->dataLen; } OsalMemFree(array); diff --git a/model/display/driver/lcdkit/lite_lcdkit.c b/model/display/driver/lcdkit/lite_lcdkit.c index 219543a6..c7db0d7b 100644 --- a/model/display/driver/lcdkit/lite_lcdkit.c +++ b/model/display/driver/lcdkit/lite_lcdkit.c @@ -48,7 +48,7 @@ static int32_t LcdkitInit(void) struct PanelConfig *panelCfg = GetPanelCfg(); if (panelCfg->info.intfType != MIPI_DSI) { - HDF_LOGE("%s:not support intf: %d", __func__, panelCfg->info.intfType); + HDF_LOGE("%s:not support intf: %u", __func__, panelCfg->info.intfType); return HDF_FAILURE; } ret = PowerInit(); @@ -65,6 +65,8 @@ static int32_t LcdkitInit(void) if (panelCfg->info.blk.type == BLK_PWM) { panelCfg->pwmHandle = PwmOpen(panelCfg->info.pwm.dev); if (panelCfg->pwmHandle == NULL) { + MipiDsiClose(panelCfg->dsiHandle); + panelCfg->dsiHandle = NULL; HDF_LOGE("%s: PwmOpen failed", __func__); return HDF_FAILURE; } @@ -222,8 +224,8 @@ static int32_t SetBacklightByMipi(uint32_t level) { int32_t ret; struct PanelConfig *panelCfg = GetPanelCfg(); - uint8_t payLoad[] = { 0x51, 0x00 }; - struct DsiCmdDesc bklCmd = { 0x15, 0, sizeof(payLoad), payLoad }; + uint8_t payLoad[] = { 0x51, 0x00 }; // panel backlight cmd + struct DsiCmdDesc bklCmd = { 0x15, 0, sizeof(payLoad), payLoad }; // dsi backlight cmd if (panelCfg->dsiHandle == NULL) { HDF_LOGE("%s: dsiHandle is null", __func__); diff --git a/model/display/driver/panel/mipi_icn9700.c b/model/display/driver/panel/mipi_icn9700.c index d63f207f..311e4c60 100644 --- a/model/display/driver/panel/mipi_icn9700.c +++ b/model/display/driver/panel/mipi_icn9700.c @@ -28,12 +28,12 @@ #define HORIZONTAL_BACK_PORCH 20 #define HORIZONTAL_FRONT_PORCH 20 #define HORIZONTAL_SYNC_WIDTH 10 -#define VERTIACL_BACK_PORCH 14 -#define VERTIACL_FRONT_PORCH 16 -#define VERTIACL_SYNC_WIDTH 2 +#define VERTICAL_BACK_PORCH 14 +#define VERTICAL_FRONT_PORCH 16 +#define VERTICAL_SYNC_WIDTH 2 #define FRAME_RATE 60 -/* panel on commond payload */ +/* panel on command payload */ static uint8_t g_payLoad0[] = { 0xF0, 0x5A, 0x5A }; static uint8_t g_payLoad1[] = { 0xF1, 0xA5, 0xA5 }; static uint8_t g_payLoad2[] = { 0xB3, 0x03, 0x03, 0x03, 0x07, 0x05, 0x0D, 0x0F, 0x11, 0x13, 0x09, 0x0B }; @@ -84,7 +84,7 @@ struct DsiCmdDesc g_OnCmd[] = { { 0x05, 120, sizeof(g_payLoad20), g_payLoad20 }, }; -/* panel off commond payload */ +/* panel off command payload */ static uint8_t g_offPayLoad0[] = { 0x28 }; static uint8_t g_offPayLoad1[] = { 0x10 }; struct DsiCmdDesc g_offCmd[] = { @@ -257,12 +257,12 @@ static struct PanelInfo g_panelInfo = { .hbp = HORIZONTAL_BACK_PORCH, /* horizontal back porch */ .hfp = HORIZONTAL_FRONT_PORCH, /* horizontal front porch */ .hsw = HORIZONTAL_SYNC_WIDTH, /* horizontal sync width */ - .vbp = VERTIACL_BACK_PORCH, /* vertiacl back porch */ - .vfp = VERTIACL_FRONT_PORCH, /* vertiacl front porch */ - .vsw = VERTIACL_SYNC_WIDTH, /* vertiacl sync width */ + .vbp = VERTICAL_BACK_PORCH, /* vertical back porch */ + .vfp = VERTICAL_FRONT_PORCH, /* vertical front porch */ + .vsw = VERTICAL_SYNC_WIDTH, /* vertical sync width */ .frameRate = FRAME_RATE, /* frame rate */ .intfType = MIPI_DSI, /* panel interface type */ - .intfSync = OUTPUT_USER, /* output timming type */ + .intfSync = OUTPUT_USER, /* output timing type */ /* mipi config info */ .mipi = { DSI_2_LANES, DSI_VIDEO_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT }, /* backlight config info */ @@ -270,8 +270,14 @@ static struct PanelInfo g_panelInfo = { .pwm = { BLK_PWM1, PWM_MAX_PERIOD }, }; +static struct PanelStatus g_panelStatus = { + .powerStatus = POWER_STATUS_OFF, + .currLevel = MIN_LEVEL, +}; + static struct PanelData g_panelData = { .info = &g_panelInfo, + .status = &g_panelStatus, .init = Icn9700Init, .on = Icn9700On, .off = Icn9700Off, diff --git a/model/display/driver/panel/ssp_st7789.c b/model/display/driver/panel/ssp_st7789.c index e19a625b..7dec843a 100644 --- a/model/display/driver/panel/ssp_st7789.c +++ b/model/display/driver/panel/ssp_st7789.c @@ -124,24 +124,24 @@ static int32_t LcdResetOn(void) ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT); if (ret != HDF_SUCCESS) { - HDF_LOGE("GpioSetDir failed, ret:%d", ret); + HDF_LOGE("set lcd reset dir failed, ret:%d", ret); return HDF_FAILURE; } ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH); if (ret != HDF_SUCCESS) { - HDF_LOGE("GpioWrite failed, ret:%d", ret); + HDF_LOGE("set lcd reset hi failed, ret:%d", ret); return HDF_FAILURE; } ret = GpioWrite(RESET_GPIO, GPIO_VAL_LOW); if (ret != HDF_SUCCESS) { - HDF_LOGE("GpioWrite failed, ret:%d", ret); + HDF_LOGE("set lcd reset how failed, ret:%d", ret); return HDF_FAILURE; } /* delay 10ms */ OsalMSleep(10); ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH); if (ret != HDF_SUCCESS) { - HDF_LOGE("GpioWrite failed, ret:%d", ret); + HDF_LOGE("set lcd reset hi after delay failed, ret:%d", ret); return HDF_FAILURE; } /* delay 120ms */ diff --git a/model/display/driver/panel/ssp_st7789.h b/model/display/driver/panel/ssp_st7789.h index 22f2356e..b80cebe9 100644 --- a/model/display/driver/panel/ssp_st7789.h +++ b/model/display/driver/panel/ssp_st7789.h @@ -16,7 +16,6 @@ #define BITS_PER_BYTE 8 #define BITS_PER_WORD 9 #define SPI_MAX_SPEED 115200 -#define SYS_WRITEL(addr, value) ((*(volatile unsigned int *)(addr)) = (value)) struct LcdCmd { uint8_t cmd; diff --git a/model/input/driver/event_hub.c b/model/input/driver/event_hub.c index 3c11bc4c..264e63c7 100644 --- a/model/input/driver/event_hub.c +++ b/model/input/driver/event_hub.c @@ -26,6 +26,12 @@ void PushOnePackage(InputDevice *inputDev, uint32_t type, uint32_t code, int32_t { OsalTimespec time; EventPackage package = {0}; + + if (inputDev == NULL) { + HDF_LOGE("%s: parm is null", __func__); + return; + } + package.type = type; package.code = code; package.value = value; diff --git a/model/input/driver/hdf_hid.c b/model/input/driver/hdf_hid.c deleted file mode 100755 index 5cd3ee27..00000000 --- a/model/input/driver/hdf_hid.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 "hdf_device_desc.h" -#include "hdf_log.h" - -static int32_t HdfHIDDriverInit(struct HdfDeviceObject *device) -{ - (void)device; - return HDF_SUCCESS; -} - -static int32_t HdfHIDDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply) -{ - (void)cmd; - if (client == NULL || data == NULL || reply == NULL) { - HDF_LOGE("%s: param is null", __func__); - return HDF_FAILURE; - } - return HDF_SUCCESS; -} - -static int32_t HdfHIDDriverBind(struct HdfDeviceObject *device) -{ - if (device == NULL) { - return HDF_ERR_INVALID_PARAM; - } - static struct IDeviceIoService hidService = { - .Dispatch = HdfHIDDispatch, - }; - device->service = &hidService; - return HDF_SUCCESS; -} - -struct HdfDriverEntry g_hdfHIDEntry = { - .moduleVersion = 1, - .moduleName = "HDF_HID", - .Bind = HdfHIDDriverBind, - .Init = HdfHIDDriverInit, -}; - -HDF_INIT(g_hdfHIDEntry); \ No newline at end of file diff --git a/model/input/driver/hdf_hid_adapter.c b/model/input/driver/hdf_hid_adapter.c new file mode 100644 index 00000000..b6e2218d --- /dev/null +++ b/model/input/driver/hdf_hid_adapter.c @@ -0,0 +1,164 @@ +/* + * 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 "hdf_device_desc.h" +#include "osal_mem.h" +#include "hdf_log.h" +#include "event_hub.h" +#include "hdf_input_device_manager.h" +#include "hdf_hid_adapter.h" + +InputDevice *cachedHid[MAX_INPUT_DEV_NUM]; + +static bool HaveHidCache(void) +{ + if (cachedHid[0] == NULL) { + return false; + } + return true; +} + +static void LoadCachedHid(void) +{ + int32_t i = 0; + int32_t ret; + if (!HaveHidCache()) { + HDF_LOGI("%s: exit", __func__); + return; + } + while (i < MAX_INPUT_DEV_NUM && cachedHid[i] != NULL) { + ret = RegisterInputDevice(cachedHid[i]); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: add %s failed", __func__, cachedHid[i]->devName); + } + cachedHid[i] = NULL; + i++; + } +} + +static InputDevice* HidConstructInputDev(HidInfo info) +{ + InputDevice *inputDev = (InputDevice *)OsalMemAlloc(sizeof(InputDevice)); + if (inputDev == NULL) { + HDF_LOGE("%s: instance input device failed", __func__); + return NULL; + } + (void)memset_s(inputDev, sizeof(InputDevice), 0, sizeof(InputDevice)); + + inputDev->devType = info.devType; + inputDev->devName = info.devName; + return inputDev; +} + +static InputDevice* DoRegisterInputDev(InputDevice* inputDev) +{ + int32_t ret; + + ret = RegisterInputDevice(inputDev); + if (ret == HDF_SUCCESS) { + return inputDev; + } else { + OsalMemFree(inputDev); + inputDev = NULL; + return NULL; + } +} + +static InputDevice* CacheHid(InputDevice* inputDev) +{ + int32_t i = 0; + while ((i < MAX_INPUT_DEV_NUM) && (cachedHid[i] != NULL)) { + i++; + } + if (i < MAX_INPUT_DEV_NUM) { + cachedHid[i] = inputDev; + return inputDev; + } + return NULL; +} + +static bool InputDriverLoaded(void) +{ + InputManager* g_inputManager = GetInputManager(); + if ((g_inputManager != NULL) && (g_inputManager->initialized != false)) { + return true; + } + return false; +} + +void* HidRegisterHdfInputDev(HidInfo info) +{ + InputDevice* inputDev = HidConstructInputDev(info); + if (inputDev == NULL) { + HDF_LOGE("%s: hid construct input Dev failed", __func__); + return NULL; + } + + if (InputDriverLoaded()) { + return DoRegisterInputDev(inputDev); + } else { + return CacheHid(inputDev); + } +} + +void HidUnregisterHdfInputDev(const void *inputDev) +{ + if (inputDev == NULL) { + HDF_LOGE("%s: inputDev is null", __func__); + } + UnregisterInputDevice((InputDevice *)inputDev); + inputDev = NULL; +} + +void HidReportEvent(const void *inputDev, uint32_t type, uint32_t code, int32_t value) +{ + PushOnePackage((InputDevice *)inputDev, type, code, value); +} + +static int32_t HdfHIDDriverInit(struct HdfDeviceObject *device) +{ + (void)device; + static bool cachedHidRegistered = false; + if (!cachedHidRegistered) { + cachedHidRegistered = true; + LoadCachedHid(); + } + return HDF_SUCCESS; +} + +static int32_t HdfHIDDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + (void)cmd; + if (client == NULL || data == NULL || reply == NULL) { + HDF_LOGE("%s: param is null", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t HdfHIDDriverBind(struct HdfDeviceObject *device) +{ + if (device == NULL) { + return HDF_ERR_INVALID_PARAM; + } + static struct IDeviceIoService hidService = { + .Dispatch = HdfHIDDispatch, + }; + device->service = &hidService; + return HDF_SUCCESS; +} + +struct HdfDriverEntry g_hdfHIDEntry = { + .moduleVersion = 1, + .moduleName = "HDF_HID", + .Bind = HdfHIDDriverBind, + .Init = HdfHIDDriverInit, +}; + +HDF_INIT(g_hdfHIDEntry); \ No newline at end of file diff --git a/model/input/driver/hdf_hid_adapter.h b/model/input/driver/hdf_hid_adapter.h new file mode 100644 index 00000000..fc2aac7b --- /dev/null +++ b/model/input/driver/hdf_hid_adapter.h @@ -0,0 +1,27 @@ +/* + * 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_HID_ADAPTER_H +#define HDF_HID_ADAPTER_H +typedef struct HidInformation { + uint32_t devType; + const char *devName; +} HidInfo; + +enum HidType { + HID_TYPE_BEGIN_POS = 33, /* HID type start position */ + HID_TYPE_MOUSE, /* Mouse */ + HID_TYPE_KEYBOARD, /* Keyboard */ + HID_TYPE_UNKNOWN, /* Unknown input device type */ +}; + +void* HidRegisterHdfInputDev(HidInfo dev); +void HidUnregisterHdfInputDev(const void *inputDev); +void HidReportEvent(const void *inputDev, uint32_t type, uint32_t code, int32_t value); + +#endif \ No newline at end of file diff --git a/model/input/driver/hdf_input_device_manager.c b/model/input/driver/hdf_input_device_manager.c index f0b0b37a..83aedce5 100644 --- a/model/input/driver/hdf_input_device_manager.c +++ b/model/input/driver/hdf_input_device_manager.c @@ -16,22 +16,25 @@ #include "hdf_input_device_manager.h" #define NODE_MODE 0660 -#define SERVICE_NAME_LEN 16 +#define SERVICE_NAME_LEN 24 #define INPUT_DEV_EXIST 1 #define INPUT_DEV_NOT_EXIST 0 -#define MOUSE_DEV_ID 2 -#define MAX_INPUT_DEV_NUM 32 #define INPUTDEV_FIRST_ID 1 #define FILLER_FLAG 1 +#define PLACEHOLDER_LENGTH 2 +#define PLACEHOLDER_LIMIT 10 -InputManager *g_inputManager; +static InputManager *g_inputManager; + +InputManager* GetInputManager(void) +{ + return g_inputManager; +} #ifndef __KERNEL__ int32_t TouchIoctl(InputDevice *inputdev, int32_t cmd, unsigned long arg); uint32_t TouchPoll(struct file *filep, InputDevice *inputDev, poll_table *wait); -#endif -#ifndef __KERNEL__ static int32_t InputDevIoctl(struct file *filep, int32_t cmd, unsigned long arg) { int32_t ret; @@ -76,7 +79,7 @@ static int32_t InputDevClose(struct file *filep) static int32_t InputDevPoll(struct file *filep, poll_table *wait) { uint32_t pollMask = 0; - InputDevice *inputdev = (InputDevice *)((struct drv_data*)filep->f_vnode->data)->priv; + InputDevice *inputdev = (InputDevice *)(InputDevice *)((struct drv_data*)filep->f_vnode->data)->priv; switch (inputdev->devType) { case INDEV_TYPE_TOUCH: pollMask = TouchPoll(filep, inputdev, wait); @@ -102,7 +105,7 @@ static const struct file_operations_vfs inputDevOps = { static bool IsHidDevice(uint32_t devType) { - if (devType == INDEV_TYPE_MOUSE) { + if ((devType > INDEV_TYPE_HID_BEGIN_POS) && (devType < INDEV_TYPE_UNKNOWN)) { return true; } return false; @@ -113,7 +116,10 @@ static struct HdfDeviceObject *HidRegisterHdfDevice(InputDevice *inputDev) char svcName[SERVICE_NAME_LEN] = {0}; const char *moduleName = "HDF_HID"; struct HdfDeviceObject *hdfDev = NULL; - int32_t ret = snprintf_s(svcName, SERVICE_NAME_LEN, strlen("event") + 1, "%s%u", "event", MOUSE_DEV_ID); + + int32_t len = (inputDev->devId < PLACEHOLDER_LIMIT) ? 1 : PLACEHOLDER_LENGTH; + int32_t ret = snprintf_s(svcName, SERVICE_NAME_LEN, strlen("hdf_input_event") + len, "%s%u", + "hdf_input_event", inputDev->devId); if (ret < 0) { HDF_LOGE("%s: snprintf_s failed", __func__); return NULL; @@ -127,6 +133,33 @@ static struct HdfDeviceObject *HidRegisterHdfDevice(InputDevice *inputDev) return hdfDev; } +static void HotPlugNotify(const InputDevice *inputDev, bool status) +{ + struct HdfSBuf *sbuf = NULL; + HotPlugEvent event = {0}; + int32_t ret; + + sbuf = HdfSBufObtain(sizeof(HotPlugEvent)); + if (sbuf == NULL) { + HDF_LOGE("%s: obtain buffer failed", __func__); + return; + } + event.devId = inputDev->devId; + event.devType = inputDev->devType; + event.status = status; + + if (!HdfSbufWriteBuffer(sbuf, &event, sizeof(HotPlugEvent))) { + HDF_LOGE("%s: write buffer failed", __func__); + goto EXIT; + } + ret = HdfDeviceSendEvent(g_inputManager->hdfDevObj, 0, sbuf); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: send event failed", __func__); + } +EXIT: + HdfSBufRecycle(sbuf); +} + static int32_t CreateDeviceNode(InputDevice *inputDev) { if (IsHidDevice(inputDev->devType)) { @@ -135,13 +168,14 @@ static int32_t CreateDeviceNode(InputDevice *inputDev) if (inputDev->hdfDevObj == NULL) { return HDF_DEV_ERR_NO_DEVICE; } - inputDev->devId = MOUSE_DEV_ID; } #ifndef __KERNEL__ - char devNode[INPUT_DEV_PATH_LEN] = {0}; - int32_t ret = snprintf_s(devNode, INPUT_DEV_PATH_LEN, strlen("/dev/input/event") + 1, - "%s%u", "/dev/input/event", inputDev->devId); + char *devNode = (char *)malloc(INPUT_DEV_PATH_LEN); + (void)memset_s(devNode, INPUT_DEV_PATH_LEN, 0, INPUT_DEV_PATH_LEN); + + int32_t ret = snprintf_s(devNode, INPUT_DEV_PATH_LEN, strlen("/dev/input/hdf_input_event") + 1, + "%s%u", "/dev/input/hdf_input_event", inputDev->devId); if (ret < 0) { HDF_LOGE("%s: snprintf_s failed", __func__); return HDF_FAILURE; @@ -164,7 +198,10 @@ static void DeleteDeviceNode(InputDevice *inputDev) if (IsHidDevice(inputDev->devType)) { char svcName[SERVICE_NAME_LEN] = {0}; const char *moduleName = "HDF_HID"; - int32_t ret = snprintf_s(svcName, SERVICE_NAME_LEN, strlen("event") + 1, "%s%u", "event", MOUSE_DEV_ID); + + int32_t len = (inputDev->devId < PLACEHOLDER_LIMIT) ? 1 : PLACEHOLDER_LENGTH; + int32_t ret = snprintf_s(svcName, SERVICE_NAME_LEN, strlen("hdf_input_event") + len, "%s%u", + "hdf_input_event", inputDev->devId); if (ret < 0) { HDF_LOGE("%s: snprintf_s failed", __func__); return; @@ -174,18 +211,12 @@ static void DeleteDeviceNode(InputDevice *inputDev) } #ifndef __KERNEL__ - char devNode[INPUT_DEV_PATH_LEN] = {0}; - int32_t ret = snprintf_s(devNode, INPUT_DEV_PATH_LEN, strlen("/dev/input/event") + 1, "%s%u", - "/dev/input/event", inputDev->devId); - if (ret < 0) { - HDF_LOGE("%s: snprintf_s failed", __func__); - return; - } - inputDev->devNode = devNode; - ret = unregister_driver(inputDev->devNode); + int32_t ret = unregister_driver(inputDev->devNode); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: delete dev node failed, ret %d", __func__, ret); } + free((void *)inputDev->devNode); + inputDev->devNode = NULL; #endif HDF_LOGI("%s: delete node succ, devId is %d", __func__, inputDev->devId); } @@ -208,6 +239,7 @@ static void AddInputDevice(InputDevice *inputDev) } } g_inputManager->devCount++; + HotPlugNotify(inputDev, ONLINE); } static int32_t CheckInputDevice(InputDevice *inputDev) @@ -254,12 +286,14 @@ static int32_t DeleteInputDevice(InputDevice *inputDev) EXIT: g_inputManager->devCount--; + HotPlugNotify(inputDev, OFFLINE); return HDF_SUCCESS; } #define DEFAULT_TOUCH_BUF_PKG_NUM 50 #define DEFAULT_KEY_BUF_PKG_NUM 10 #define DEFAULT_MOUSE_BUF_PKG_NUM 30 +#define DEFAULT_KEYBOARD_BUF_PKG_NUM 20 #define DEFAULT_CROWN_BUF_PKG_NUM 20 #define DEFAULT_ENCODER_BUF_PKG_NUM 20 @@ -276,6 +310,9 @@ static int32_t AllocPackageBuffer(InputDevice *inputDev) case INDEV_TYPE_MOUSE: pkgNum = DEFAULT_MOUSE_BUF_PKG_NUM; break; + case INDEV_TYPE_KEYBOARD: + pkgNum = DEFAULT_KEYBOARD_BUF_PKG_NUM; + break; case INDEV_TYPE_CROWN: pkgNum = DEFAULT_CROWN_BUF_PKG_NUM; break; @@ -309,14 +346,12 @@ static uint32_t AllocDeviceID(InputDevice *inputDev) tmpDev = tmpDev->next; } for (id = INPUTDEV_FIRST_ID; id < MAX_INPUT_DEV_NUM + 1; id++) { - if (id == MOUSE_DEV_ID) { - continue; - } if (idList[id] == 0) { inputDev->devId = id; return HDF_SUCCESS; } } + HDF_LOGE("%s: alloc device id failed", __func__); return HDF_FAILURE; } @@ -330,7 +365,7 @@ int32_t RegisterInputDevice(InputDevice *inputDev) return HDF_ERR_INVALID_PARAM; } - if (g_inputManager == NULL || g_inputManager->initialized == false) { + if ((g_inputManager == NULL) || (g_inputManager->initialized == false)) { HDF_LOGE("%s: dev manager is null or initialized failed", __func__); return HDF_FAILURE; } @@ -362,18 +397,18 @@ EXIT: return ret; } -int32_t UnregisterInputDevice(InputDevice *inputDev) +void UnregisterInputDevice(InputDevice *inputDev) { - int ret = HDF_FAILURE; + int32_t ret; HDF_LOGI("%s: enter", __func__); if (inputDev == NULL) { HDF_LOGE("%s: inputdev is null", __func__); - return HDF_ERR_INVALID_PARAM; + return; } - if (g_inputManager == NULL || g_inputManager->initialized == false) { + if ((g_inputManager == NULL) || (g_inputManager->initialized == false)) { HDF_LOGE("%s: dev manager is null or initialized failed", __func__); - return HDF_FAILURE; + return; } OsalMutexLock(&g_inputManager->mutex); @@ -389,14 +424,15 @@ int32_t UnregisterInputDevice(InputDevice *inputDev) if (ret != HDF_SUCCESS) { goto EXIT; } - + OsalMemFree(inputDev); + inputDev = NULL; OsalMutexUnlock(&g_inputManager->mutex); HDF_LOGI("%s: exit succ, devCount is %d", __func__, g_inputManager->devCount); - return HDF_SUCCESS; + return; EXIT: OsalMutexUnlock(&g_inputManager->mutex); - return ret; + return; } static uint32_t GetDeviceCount(void) @@ -405,6 +441,40 @@ static uint32_t GetDeviceCount(void) return g_inputManager->devCount; } +static int32_t ScanAllDev(struct HdfSBuf *reply) +{ + DevDesc sta; + InputDevice *tmpDev = g_inputManager->inputDevList; + while (tmpDev != NULL) { + sta.devType = tmpDev->devType; + sta.devId = tmpDev->devId; + + if (!HdfSbufWriteBuffer(reply, &sta, sizeof(DevDesc))) { + HDF_LOGE("%s: HdfSbufWriteBuffer failed", __func__); + return HDF_FAILURE; + } + tmpDev = tmpDev->next; + } + HdfSbufWriteBuffer(reply, NULL, 0); // end flag + return HDF_SUCCESS; +} + +static int32_t ScanDevice(struct HdfDeviceIoClient *client, int32_t cmd, + struct HdfSBuf *data, struct HdfSBuf *reply) +{ + (void)cmd; + int32_t ret; + if ((client == NULL) || (data == NULL) || (reply == NULL)) { + HDF_LOGE("%s: param is null", __func__); + return HDF_FAILURE; + } + ret = ScanAllDev(reply); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: scan all dev failed", __func__); + } + return ret; +} + static int32_t HdfInputManagerBind(struct HdfDeviceObject *device) { if (device == NULL) { @@ -414,6 +484,7 @@ static int32_t HdfInputManagerBind(struct HdfDeviceObject *device) static IInputManagerService managerService = { .getDeviceCount = GetDeviceCount, + .ioService.Dispatch = ScanDevice, }; device->service = &managerService.ioService; diff --git a/model/input/driver/hdf_input_device_manager.h b/model/input/driver/hdf_input_device_manager.h index 93c54049..41798661 100644 --- a/model/input/driver/hdf_input_device_manager.h +++ b/model/input/driver/hdf_input_device_manager.h @@ -19,7 +19,10 @@ #endif #define HDF_LOG_TAG HDF_INPUT_DRV #define INPUT_DEV_PATH_LEN 64 +#define MAX_INPUT_DEV_NUM 32 #define DEV_NAME_LEN 16 +#define ONLINE 0 +#define OFFLINE 1 #define CHECK_RETURN_VALUE(ret) do { \ if ((ret) != HDF_SUCCESS) { \ @@ -27,6 +30,17 @@ } \ } while (0) +typedef struct { + uint32_t devId; + uint32_t devType; +} DevDesc; + +typedef struct { + uint32_t devId; + uint32_t devType; + uint32_t status; +} HotPlugEvent; + typedef struct { struct IDeviceIoService ioService; uint32_t (*getDeviceCount)(void); @@ -55,14 +69,15 @@ typedef struct { } InputManager; enum InputDevType { - INDEV_TYPE_TOUCH, /* Touchscreen */ - INDEV_TYPE_KEY, /* Physical key */ - INDEV_TYPE_KEYBOARD, /* Keyboard */ - INDEV_TYPE_MOUSE, /* Mouse */ - INDEV_TYPE_BUTTON, /* Virtual button */ - INDEV_TYPE_CROWN, /* Watch crown */ - INDEV_TYPE_ENCODER, /* Customized type of a specific function or event */ - INDEV_TYPE_UNKNOWN, /* Unknown input device type */ + INDEV_TYPE_TOUCH, /* Touchscreen */ + INDEV_TYPE_KEY, /* Physical key */ + INDEV_TYPE_BUTTON, /* Virtual button */ + INDEV_TYPE_CROWN, /* Watch crown */ + INDEV_TYPE_ENCODER, /* Customized type of a specific function or event */ + INDEV_TYPE_HID_BEGIN_POS = 33, /* HID type start position */ + INDEV_TYPE_MOUSE, /* Mouse */ + INDEV_TYPE_KEYBOARD, /* Keyboard */ + INDEV_TYPE_UNKNOWN, /* Unknown input device type */ }; enum InputIOsvcCmdId { @@ -89,8 +104,8 @@ enum TouchIoctlCmd { INPUT_IOCTL_RUN_CAPACITANCE_TEST, INPUT_IOCTL_RUN_EXTRA_CMD, }; - +InputManager* GetInputManager(void); int32_t RegisterInputDevice(InputDevice *device); -int32_t UnregisterInputDevice(InputDevice *device); +void UnregisterInputDevice(InputDevice *device); #endif \ No newline at end of file diff --git a/model/input/driver/hdf_key.c b/model/input/driver/hdf_key.c index 8b07dacd..154df2df 100644 --- a/model/input/driver/hdf_key.c +++ b/model/input/driver/hdf_key.c @@ -14,8 +14,8 @@ #include "event_hub.h" #include "hdf_key.h" -#define CHECK_PARSER_RET(ret, str) do { \ - if (ret != HDF_SUCCESS) { \ +#define CHECK_PARSER_RET(ret, str) do { \ + if ((ret) != HDF_SUCCESS) { \ HDF_LOGE("%s: %s failed, ret = %d!", __func__, str, ret); \ return HDF_FAILURE; \ } \ @@ -40,7 +40,10 @@ static int32_t IoctlReadKeyEvent(KeyDriver *driver, unsigned long arg) int32_t KeyIoctl(InputDevice *inputdev, int32_t cmd, unsigned long arg) { - int32_t ret; + int32_t ret = HDF_FAILURE; + if (inputdev == NULL) { + return ret; + } KeyDriver *driver = (KeyDriver *)inputdev->pvtData; switch (cmd) { case INPUT_IOCTL_GET_EVENT_DATA: @@ -58,7 +61,13 @@ int32_t KeyIrqHandle(uint16_t intGpioNum, void *data) { uint16_t gpioValue; KeyDriver *driver = (KeyDriver *)data; + if (driver == NULL) { + return HDF_FAILURE; + } KeyEventData *event = &driver->eventData; + if (event == NULL) { + return HDF_FAILURE; + } int32_t ret = GpioDisableIrq(intGpioNum); if (ret != HDF_SUCCESS) { diff --git a/model/input/driver/hdf_touch.c b/model/input/driver/hdf_touch.c index edb8fcf3..b129da73 100644 --- a/model/input/driver/hdf_touch.c +++ b/model/input/driver/hdf_touch.c @@ -6,13 +6,13 @@ * See the LICENSE file in the root of this repository for complete details. */ +#include "hdf_touch.h" #include "gpio_if.h" #include "hdf_device_desc.h" #include "hdf_log.h" #include "osal_mem.h" #include "osal_io.h" #include "event_hub.h" -#include "hdf_touch.h" #define I2C_TYPE 0 #define SPI_TYPE 1 @@ -79,7 +79,10 @@ static int32_t IoctlGetChipName(TouchDriver *driver, unsigned long arg) int32_t TouchIoctl(InputDevice *inputdev, int32_t cmd, unsigned long arg) { - int32_t ret; + int32_t ret = HDF_FAILURE; + if (inputdev == NULL || inputdev->pvtData == NULL) { + return ret; + } ChipDevice *device = (ChipDevice *)inputdev->pvtData; TouchDriver *driver = device->driver; switch (cmd) { @@ -104,6 +107,9 @@ int32_t TouchIoctl(InputDevice *inputdev, int32_t cmd, unsigned long arg) uint32_t TouchPoll(FAR struct file *filep, InputDevice *inputDev, poll_table *wait) { uint32_t pollMask = 0; + if (filep == NULL || filep->f_vnode == NULL) { + return pollMask; + } InputDevice *inputdev = (InputDevice *)((struct drv_data*)filep->f_vnode->data)->priv; if (inputdev == NULL) { HDF_LOGE("%s: inputdev is null", __func__); @@ -124,7 +130,7 @@ uint32_t TouchPoll(FAR struct file *filep, InputDevice *inputDev, poll_table *wa static int32_t SetGpioDirAndLevel(int gpio, int dir, int level) { int32_t ret; - if (dir == GPIO_DIR_IN || dir == GPIO_DIR_OUT) { + if ((dir == GPIO_DIR_IN) || (dir == GPIO_DIR_OUT)) { ret = GpioSetDir(gpio, dir); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: set gpio%d to %d dir failed, ret %d", __func__, gpio, dir, ret); @@ -132,7 +138,7 @@ static int32_t SetGpioDirAndLevel(int gpio, int dir, int level) } } - if (level == GPIO_VAL_LOW || level == GPIO_VAL_HIGH) { + if ((level == GPIO_VAL_LOW) || (level == GPIO_VAL_HIGH)) { ret = GpioWrite(gpio, level); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: pull gpio%d to %d level failed, ret %d", __func__, gpio, level, ret); @@ -161,15 +167,20 @@ static int32_t SetGpio(uint16_t gpio, uint32_t dir, uint32_t status) return HDF_SUCCESS; } -int32_t HandlePowerEvent(ChipDevice *chipDev, uint32_t *timing) +static int32_t HandlePowerEvent(ChipDevice *chipDev, uint32_t *timing, uint32_t length) { int32_t ret = 0; uint16_t gpio; + + if (length <= PWR_DELAY_INDEX) { + HDF_LOGE("%s: invalid param", __func__); + return HDF_FAILURE; + } uint32_t type = timing[PWR_TYPE_INDEX]; uint32_t status = timing[PWR_STATUS_INDEX]; uint32_t dir = timing[PWR_DIR_INDEX]; uint32_t delay = timing[PWR_DELAY_INDEX]; - HDF_LOGD("%s: type = %d, status = %d, dir = %d, delay = %d", __func__, type, status, dir, delay); + HDF_LOGD("%s: type = %u, status = %u, dir = %u, delay = %u", __func__, type, status, dir, delay); switch (type) { case TYPE_VCC: @@ -253,7 +264,7 @@ static int32_t SetPowerOnTiming(ChipDevice *chipDev) } for (i = 0; i < pwrOnTiming.count / PWR_CELL_LEN; i++) { - ret = HandlePowerEvent(chipDev, pwrOnTiming.buf); + ret = HandlePowerEvent(chipDev, pwrOnTiming.buf, PWR_CELL_LEN); CHECK_RETURN_VALUE(ret); pwrOnTiming.buf = pwrOnTiming.buf + PWR_CELL_LEN; } @@ -273,12 +284,13 @@ static void EventHandle(TouchDriver *driver, ChipDevice *chipDev) } } -int32_t IrqHandle(uint16_t intGpioNum, void *data) +static int32_t IrqHandle(uint16_t intGpioNum, void *data) { TouchDriver *driver = (TouchDriver *)data; int ret = GpioDisableIrq(intGpioNum); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: disable irq failed, ret %d", __func__, ret); + return HDF_FAILURE; } EventHandle(driver, driver->device); @@ -286,6 +298,7 @@ int32_t IrqHandle(uint16_t intGpioNum, void *data) ret = GpioEnableIrq(intGpioNum); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: enable irq failed, ret %d", __func__, ret); + return HDF_FAILURE; } return HDF_SUCCESS; } @@ -302,6 +315,7 @@ static void InputFrameReport(TouchDriver *driver) input_report_abs(dev, ABS_MT_POSITION_X, frame->fingers[i].x); input_report_abs(dev, ABS_MT_POSITION_Y, frame->fingers[i].y); input_report_abs(dev, ABS_MT_TRACKING_ID, frame->fingers[i].trackId); + input_mt_sync(dev); } } @@ -320,8 +334,12 @@ static int32_t SetupChipIrq(ChipDevice *chipDev) uint16_t intGpioNum = chipDev->boardCfg->pins.intGpio; uint16_t irqFlag = chipDev->chipCfg->bus.chipI2c.irqFlag; + if (chipDev->driver == NULL) { + HDF_LOGE("%s: invalid param", __func__); + return HDF_FAILURE; + } irqFlag |= GPIO_IRQ_USING_THREAD; - HDF_LOGD("%s: gpioNum = %d, irqFlag = %d", __func__, intGpioNum, irqFlag); + HDF_LOGD("%s: gpioNum = %u, irqFlag = %u", __func__, intGpioNum, irqFlag); ret = GpioSetIrq(intGpioNum, irqFlag, IrqHandle, chipDev->driver); if (ret != 0) { HDF_LOGE("%s: register irq failed, ret %d", __func__, ret); @@ -349,6 +367,10 @@ static int32_t ChipDriverInit(ChipDevice *chipDev) CHECK_RETURN_VALUE(ret); HDF_LOGI("%s: chipDetect succ, ret = %d ", __func__, ret); + ret = chipDev->ops->UpdateFirmware(chipDev); + CHECK_RETURN_VALUE(ret); + HDF_LOGI("%s: update firmware success", __func__); + ret = SetupChipIrq(chipDev); CHECK_RETURN_VALUE(ret); return HDF_SUCCESS; @@ -377,12 +399,12 @@ static int32_t ChipMatchCheck(const ChipDevice *chipDev, const TouchDriver *driv const struct DeviceResourceNode *boardNode = driver->boardCfg->boardNode; const struct DeviceResourceNode *chipNode = chipDev->chipCfg->chipNode; - if (boardNode == NULL || boardNode->parent == NULL) { + if ((boardNode == NULL) || (boardNode->parent == NULL)) { HDF_LOGE("%s: board node or upper node is null", __func__); return HDF_FAILURE; } - if (chipNode == NULL || chipNode->parent == NULL || chipNode->parent->parent == NULL) { + if ((chipNode == NULL) || (chipNode->parent == NULL) || (chipNode->parent->parent == NULL)) { HDF_LOGE("%s: chip node or upper node is null ", __func__); return HDF_FAILURE; } @@ -410,7 +432,7 @@ static int32_t DeviceBindDriver(ChipDevice *chipDev) } } - if (ret == HDF_FAILURE || driver == NULL) { + if ((ret == HDF_FAILURE) || (driver == NULL)) { return HDF_FAILURE; } @@ -462,7 +484,7 @@ EXIT: static int32_t TouchGetDevType(TouchDriver *driver, struct HdfSBuf *reply) { uint32_t devType = driver->devType; - HDF_LOGI("%s: enter, devType is %d", __func__, devType); + HDF_LOGI("%s: enter, devType is %u", __func__, devType); bool ret = HdfSbufWriteUint32(reply, devType); if (!ret) { HDF_LOGE("%s: HdfSbufWriteUint32 failed", __func__); @@ -480,7 +502,7 @@ static int32_t TouchSetPowerStatus(TouchDriver *driver, struct HdfSBuf *data) return HDF_FAILURE; } driver->pwrStatus = pwrStatus; - HDF_LOGI("%s: set power status is %d", __func__, pwrStatus); + HDF_LOGI("%s: set power status is %u", __func__, pwrStatus); return HDF_SUCCESS; } @@ -492,14 +514,14 @@ static int32_t TouchGetPowerStatus(TouchDriver *driver, struct HdfSBuf *reply) HDF_LOGE("%s: HdfSbufWriteUint32 failed", __func__); return HDF_FAILURE; } - HDF_LOGI("%s: get power status is %d", __func__, pwrStatus); + HDF_LOGI("%s: get power status is %u", __func__, pwrStatus); return HDF_SUCCESS; } static int32_t TouchGetDeviceInfo(TouchDriver *driver, int32_t cmd, struct HdfSBuf *reply) { - const char *info; - if (driver->device == NULL || driver->device->chipCfg == NULL) { + const char *info = NULL; + if ((driver->device == NULL) || (driver->device->chipCfg == NULL)) { HDF_LOGE("%s: parameter invalid", __func__); return HDF_ERR_INVALID_PARAM; } @@ -537,7 +559,7 @@ static int32_t TouchSetGestureMode(TouchDriver *driver, struct HdfSBuf *data) return HDF_FAILURE; } driver->gestureMode = gestureMode; - HDF_LOGD("%s: set gesture mode is %d", __func__, gestureMode); + HDF_LOGD("%s: set gesture mode is %u", __func__, gestureMode); return HDF_SUCCESS; } @@ -560,7 +582,7 @@ static int32_t TouchSelfCapacitance(TouchDriver *driver, struct HdfSBuf *data, s HDF_LOGE("%s: HdfSbufWriteString failed", __func__); return HDF_FAILURE; } - HDF_LOGD("%s: capac test type is %d, test result is %s", __func__, capacTest.testType, capacTest.testResult); + HDF_LOGD("%s: capac test type is %u, test result is %s", __func__, capacTest.testType, capacTest.testResult); return HDF_SUCCESS; } @@ -585,10 +607,9 @@ static int32_t TouchRunExtraCmd(TouchDriver *driver, struct HdfSBuf *data) static int32_t HdfTouchDispatch(struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply) { - (void)cmd; int32_t ret; TouchDriver *touchDriver = NULL; - if (client == NULL || client->device == NULL || data == NULL || reply == NULL) { + if ((client == NULL) || (client->device == NULL) || (data == NULL) || (reply == NULL)) { HDF_LOGE("%s: param is null", __func__); return HDF_FAILURE; } @@ -809,8 +830,7 @@ static void HdfTouchDriverRelease(struct HdfDeviceObject *device) } if (inputDev != NULL) { - (void)UnregisterInputDevice(inputDev); - OsalMemFree(inputDev); + UnregisterInputDevice(inputDev); driver->inputDev = NULL; } diff --git a/model/input/driver/hdf_touch.h b/model/input/driver/hdf_touch.h index 18f31a0f..968f8201 100644 --- a/model/input/driver/hdf_touch.h +++ b/model/input/driver/hdf_touch.h @@ -96,6 +96,7 @@ struct TouchChipOps { int32_t (*Resume)(ChipDevice *device); int32_t (*Suspend)(ChipDevice *device); int32_t (*DataHandle)(ChipDevice *device); + int32_t (*UpdateFirmware)(ChipDevice *device); }; typedef struct { diff --git a/model/input/driver/input_config_parser.c b/model/input/driver/input_config_parser.c index d6fb06e8..f6c49eba 100644 --- a/model/input/driver/input_config_parser.c +++ b/model/input/driver/input_config_parser.c @@ -20,6 +20,8 @@ #define DEFAULT_I2C_SPEED 400 #define DEFAULT_SPI_SPEED 10000 +#define I2C 0 +#define SPI 1 int32_t ParseKeyConfig(const struct DeviceResourceNode *node, KeyChipCfg *config) { @@ -71,7 +73,7 @@ static int32_t ParseBus(struct DeviceResourceIface *parser, const struct DeviceR ret = parser->GetUint8(busNode, "busType", &bus->busType, 0); CHECK_PARSER_RET(ret, "GetUint8"); - if (bus->busType == 0) { + if (bus->busType == I2C) { ret = parser->GetUint8(busNode, "busNum", &bus->i2c.busNum, 0); CHECK_PARSER_RET(ret, "GetUint8"); ret = parser->GetUint16(busNode, "clkGpio", &bus->i2c.clkGpio, 0); @@ -82,7 +84,7 @@ static int32_t ParseBus(struct DeviceResourceIface *parser, const struct DeviceR CHECK_PARSER_RET(ret, "GetUint32Array"); ret = parser->GetUint32Array(busNode, "i2cDataIomux", bus->i2c.i2cDataReg, REG_CONFIG_LEN, 0); CHECK_PARSER_RET(ret, "GetUint32Array"); - } else if (bus->busType == 1) { + } else if (bus->busType == SPI) { ret = parser->GetUint8(busNode, "busNum", &bus->spi.busNum, 0); CHECK_PARSER_RET(ret, "GetUint8"); ret = parser->GetUint16(busNode, "clkGpio", &bus->spi.clkGpio, 0); @@ -274,7 +276,7 @@ int32_t ParseTouchChipConfig(const struct DeviceResourceNode *node, TouchChipCfg CHECK_PARSER_RET(ret, "GetUint16"); ret = parser->GetUint8(node, "busType", &config->bus.busType, 0); CHECK_PARSER_RET(ret, "GetUint8"); - if (config->bus.busType == 0) { + if (config->bus.busType == I2C) { ret = parser->GetUint16(node, "irqFlag", &config->bus.chipI2c.irqFlag, 0); CHECK_PARSER_RET(ret, "GetUint16"); ret = parser->GetUint32(node, "deviceAddr", &config->bus.chipI2c.commAddr, 0); diff --git a/model/input/driver/touchscreen/touch_ft6336.c b/model/input/driver/touchscreen/touch_ft6336.c index cf99b79b..87a006fb 100644 --- a/model/input/driver/touchscreen/touch_ft6336.c +++ b/model/input/driver/touchscreen/touch_ft6336.c @@ -41,7 +41,7 @@ static int32_t ChipDetect(ChipDevice *device) CHIP_CHECK_RETURN(ret); ret = InputI2cRead(i2cClient, ®Addr, 1, ®Value, 1); CHIP_CHECK_RETURN(ret); - HDF_LOGI("%s: Report rate is %d * 10", __func__, regValue); + HDF_LOGI("%s: Report rate is %u * 10", __func__, regValue); regAddr = FTS_REG_FW_VER; ret = InputI2cWrite(i2cClient, ®Addr, 1); @@ -55,7 +55,7 @@ static int32_t ChipDetect(ChipDevice *device) CHIP_CHECK_RETURN(ret); ret = InputI2cRead(i2cClient, ®Addr, 1, ®Value, 1); CHIP_CHECK_RETURN(ret); - HDF_LOGI("%s: Chip ID is %d", __func__, regValue); + HDF_LOGI("%s: Chip ID is %u", __func__, regValue); (void)ChipInit(device); (void)ChipResume(device); diff --git a/model/input/driver/touchscreen/touch_gt911.c b/model/input/driver/touchscreen/touch_gt911.c index 04edebf4..9736112e 100644 --- a/model/input/driver/touchscreen/touch_gt911.c +++ b/model/input/driver/touchscreen/touch_gt911.c @@ -80,6 +80,8 @@ static int ChipCleanBuffer(InputI2cClient *i2cClient) return ret; } +#define X_OFFSET 1 + static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum) { int32_t chipVer = device->chipCfg->chipVersion; @@ -89,10 +91,15 @@ static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, u for (i = 0; i < pointNum; i++) { if (chipVer == 0) { // chipversion A:gt911_zsj5p5 + frame->fingers[i].trackId = buf[GT_POINT_SIZE * i + GT_TRACK_ID]; frame->fingers[i].y = (buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) | ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); frame->fingers[i].x = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & ONE_BYTE_MASK) | ((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); + if (frame->fingers[i].x == 0) { + frame->fingers[i].x = X_OFFSET; + } + HDF_LOGD("%s: x = %d, y = %d", __func__, frame->fingers[i].x, frame->fingers[i].y); } else if (chipVer == 1) { // chipversion B:gt911_zsj4p0 frame->fingers[i].x = resX - 1 - ((buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) | ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET)); @@ -137,7 +144,7 @@ static int32_t ChipDataHandle(ChipDevice *device) reg[1] = GT_X_LOW_BYTE_BASE & ONE_BYTE_MASK; pointNum = touchStatus & GT_FINGER_NUM_MASK; if (pointNum == 0 || pointNum > MAX_SUPPORT_POINT) { - HDF_LOGE("%s: pointNum is invalid, %d", __func__, pointNum); + HDF_LOGE("%s: pointNum is invalid, %u", __func__, pointNum); (void)ChipCleanBuffer(i2cClient); OsalMutexUnlock(&device->driver->mutex); return HDF_FAILURE; @@ -155,12 +162,25 @@ EXIT: return HDF_SUCCESS; } +static int32_t UpdateFirmware(ChipDevice *device) +{ + int32_t ret; + InputI2cClient *i2cClient = &device->driver->i2cClient; + ret = InputI2cWrite(i2cClient, firmWareParm, FIRMWARE_LEN); + if (ret < 0) { + return HDF_FAILURE; + } + HDF_LOGI("%s: update firmware success\n", __func__); + return HDF_SUCCESS; +} + static struct TouchChipOps g_gt911ChipOps = { .Init = ChipInit, .Detect = ChipDetect, .Resume = ChipResume, .Suspend = ChipSuspend, .DataHandle = ChipDataHandle, + .UpdateFirmware = UpdateFirmware, }; static TouchChipCfg *ChipConfigInstance(struct HdfDeviceObject *device) diff --git a/model/input/driver/touchscreen/touch_gt911.h b/model/input/driver/touchscreen/touch_gt911.h index c89a344d..ebb3abf0 100644 --- a/model/input/driver/touchscreen/touch_gt911.h +++ b/model/input/driver/touchscreen/touch_gt911.h @@ -10,20 +10,21 @@ #define TOUCH_GT911_H /* the macro defines of GT911 */ -#define MAX_SUPPORT_POINT 10 +#define MAX_SUPPORT_POINT 5 #define ONE_BYTE_MASK 0xFF #define ONE_BYTE_OFFSET 8 #define GT_EVENT_UP 0x80 #define GT_EVENT_INVALID 0 #define GT_POINT_SIZE 8 -#define GT_X_LOW 0 -#define GT_X_HIGH 1 -#define GT_Y_LOW 2 -#define GT_Y_HIGH 3 +#define GT_TRACK_ID 0 +#define GT_X_LOW 1 +#define GT_X_HIGH 2 +#define GT_Y_LOW 3 +#define GT_Y_HIGH 4 #define GT_ADDR_LEN 2 #define GT_BUF_STATE_ADDR 0x814E -#define GT_X_LOW_BYTE_BASE 0x8150 +#define GT_X_LOW_BYTE_BASE 0x814F #define GT_FINGER_NUM_MASK 0x0F #define GT_CLEAN_DATA_LEN 3 #define GT_REG_HIGH_POS 0 @@ -43,5 +44,23 @@ #define GT_SOLU_X_HIGH 7 #define GT_SOLU_Y_LOW 8 #define GT_SOLU_Y_HIGH 9 +#define FIRMWARE_LEN 188 + +uint8_t firmWareParm[FIRMWARE_LEN] = { + 0x80, 0x47, 0x45, 0xC0, 0x03, 0xE0, 0x01, 0x05, 0x3D, 0x00, 0x01, 0x08, 0x28, 0x0F, + 0x50, 0x32, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1A, 0x1E, + 0x14, 0x86, 0x26, 0x08, 0x55, 0x57, 0xB2, 0x04, 0x00, 0x00, 0x00, 0x42, 0x02, 0x11, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x78, 0x94, + 0xD5, 0x02, 0x07, 0x00, 0x00, 0x04, 0x97, 0x40, 0x00, 0x8A, 0x4A, 0x00, 0x80, 0x55, + 0x00, 0x77, 0x61, 0x00, 0x6F, 0x70, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x00, 0x02, 0x04, 0x06, + 0x08, 0x0A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5C, 0x01 +}; #endif \ No newline at end of file