diff --git a/model/input/driver/hdf_encoder.c b/model/input/driver/hdf_encoder.c new file mode 100644 index 0000000000000000000000000000000000000000..134b8f610a9e4ee57e0f6863a2dece797201b1b0 --- /dev/null +++ b/model/input/driver/hdf_encoder.c @@ -0,0 +1,290 @@ +/* + * 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_encoder.h" +#include "event_hub.h" +#include "gpio_if.h" +#include "osal_mem.h" +#include "osal_timer.h" +#include "hdf_log.h" +#include "hdf_device_desc.h" + +#define TIMER_INTERVAL_ENCODER 5 + +static void EncoderTimerFunc(uintptr_t arg) +{ + EncoderDriver *encoderDrv = (EncoderDriver *)arg; + uint16_t gpioClk = encoderDrv->encoderCfg->gpioClk; + uint16_t gpioData = encoderDrv->encoderCfg->gpioData; + uint16_t gpioSW = encoderDrv->encoderCfg->gpioSW; + + int32_t ret = GpioRead(gpioClk, &encoderDrv->encoderClkNowSta); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: gpio read failed, ret %d", __func__, ret); + return; + } + ret = GpioRead(gpioData, &encoderDrv->encoderDataNowSta); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: gpio read failed, ret %d", __func__, ret); + return; + } + ret = GpioRead(gpioSW, &encoderDrv->encoderSWNowSta); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: gpio read failed, ret %d", __func__, ret); + return; + } + + if (encoderDrv->encoderClkNowSta != encoderDrv->encoderClkPreSta) { + if (encoderDrv->encoderClkNowSta == 0) { + if (encoderDrv->encoderDataNowSta == 1) { + input_report_rel(encoderDrv->inputDev, REL_WHEEL, 1); + } else { + input_report_rel(encoderDrv->inputDev, REL_WHEEL, -1); + } + input_sync(encoderDrv->inputDev); + } + encoderDrv->encoderClkPreSta = encoderDrv->encoderClkNowSta; + encoderDrv->encoderDataPreSta = encoderDrv->encoderDataNowSta; + } + if (encoderDrv->encoderSWPreSta != encoderDrv->encoderSWNowSta) { + if (encoderDrv->encoderSWNowSta == 0) { + input_report_key(encoderDrv->inputDev, KEY_OK, 0); + } else { + input_report_key(encoderDrv->inputDev, KEY_OK, 1); + } + encoderDrv->encoderSWPreSta = encoderDrv->encoderSWNowSta; + input_sync(encoderDrv->inputDev); + } +} + +static EncoderCfg *EncoderConfigInstance(struct HdfDeviceObject *device) +{ + EncoderCfg *encoderCfg = (EncoderCfg *)OsalMemAlloc(sizeof(EncoderCfg)); + if (encoderCfg == NULL) { + HDF_LOGE("%s: malloc encoder config failed", __func__); + return NULL; + } + int32_t ret = memset_s(encoderCfg, sizeof(EncoderCfg), 0, sizeof(EncoderCfg)); + if (ret != 0) { + HDF_LOGE("%s: memset_s encoder config failed", __func__); + OsalMemFree(encoderCfg); + return NULL; + } + encoderCfg->hdfEncoderDev = device; + + if (ParseEncoderConfig(device->property, encoderCfg) != HDF_SUCCESS) { + HDF_LOGE("%s: parse encoder config failed", __func__); + OsalMemFree(encoderCfg); + return NULL; + } + return encoderCfg; +} + +static EncoderDriver *EncoderDriverInstance(EncoderCfg *encoderCfg) +{ + EncoderDriver *encoderDrv = (EncoderDriver *)OsalMemAlloc(sizeof(EncoderDriver)); + if (encoderDrv == NULL) { + HDF_LOGE("%s: malloc key driver failed", __func__); + return NULL; + } + int32_t ret = memset_s(encoderDrv, sizeof(EncoderDriver), 0, sizeof(EncoderDriver)); + if (ret != 0) { + HDF_LOGE("%s: memset encoder driver failed", __func__); + OsalMemFree(encoderDrv); + return NULL; + } + + encoderDrv->devType = encoderCfg->devType; + encoderDrv->encoderCfg = encoderCfg; + + return encoderDrv; +} + +static int32_t EncoderInit(EncoderDriver *EncoderDrv) +{ + uint16_t gpioClk = EncoderDrv->encoderCfg->gpioClk; + uint16_t gpioData = EncoderDrv->encoderCfg->gpioData; + uint16_t gpioSW = EncoderDrv->encoderCfg->gpioSW; + GpioSetDir(gpioClk, GPIO_DIR_IN); + GpioSetDir(gpioData, GPIO_DIR_IN); + GpioSetDir(gpioSW, GPIO_DIR_IN); + + int32_t ret = OsalTimerCreate(&EncoderDrv->timer, TIMER_INTERVAL_ENCODER, EncoderTimerFunc, EncoderDrv); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: create timer failed, ret = %d\n", __func__, ret); + return HDF_FAILURE; + } + ret = OsalTimerStartLoop(&EncoderDrv->timer); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: start timer failed, ret = %d\n", __func__, ret); + return HDF_FAILURE; + } + + ret = GpioRead(gpioClk, &EncoderDrv->encoderClkNowSta); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: gpio read failed, ret %d", __func__, ret); + return HDF_FAILURE; + } + ret = GpioRead(gpioData, &EncoderDrv->encoderDataNowSta); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: gpio read failed, ret %d", __func__, ret); + return HDF_FAILURE; + } + ret = GpioRead(gpioSW, &EncoderDrv->encoderSWNowSta); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: gpio read failed, ret %d", __func__, ret); + return HDF_FAILURE; + } + + EncoderDrv->encoderClkPreSta = EncoderDrv->encoderClkNowSta; + EncoderDrv->encoderDataPreSta = EncoderDrv->encoderDataNowSta; + + return HDF_SUCCESS; +} + +static InputDevice *InputDeviceInstance(EncoderDriver *encoderDrv) +{ + InputDevice *inputDev = (InputDevice *)OsalMemAlloc(sizeof(InputDevice)); + if (inputDev == NULL) { + HDF_LOGE("%s: malloc input device failed", __func__); + return NULL; + } + int32_t ret = memset_s(inputDev, sizeof(InputDevice), 0, sizeof(InputDevice)); + if (ret != 0) { + HDF_LOGE("%s: memset encoder driver failed", __func__); + OsalMemFree(inputDev); + return NULL; + } + + ret = OsalMutexInit(&inputDev->mutex); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: Init mutex error", __func__); + OsalMemFree(inputDev); + return NULL; + } + + inputDev->pvtData = (void *)encoderDrv; + inputDev->devType = encoderDrv->devType; + inputDev->hdfDevObj = encoderDrv->encoderCfg->hdfEncoderDev; + encoderDrv->inputDev = inputDev; + + return inputDev; +} + +static int32_t RegisterEncoderDevice(EncoderCfg *encoderCfg, struct HdfDeviceObject *device) +{ + EncoderDriver *EncoderDrv = EncoderDriverInstance(encoderCfg); + if (EncoderDrv == NULL) { + HDF_LOGE("%s: instance encoder driver failed", __func__); + return HDF_ERR_MALLOC_FAIL; + } + device->priv = (void *)EncoderDrv; + + int32_t ret = EncoderInit(EncoderDrv); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: key driver init failed, ret %d", __func__, ret); + goto EXIT; + } + + InputDevice *inputDev = InputDeviceInstance(EncoderDrv); + if (inputDev == NULL) { + HDF_LOGE("%s: instance input device failed", __func__); + goto EXIT; + } + + ret = RegisterInputDevice(inputDev); + if (ret != HDF_SUCCESS) { + goto EXIT1; + } + return HDF_SUCCESS; + +EXIT1: + OsalMemFree(inputDev->pkgBuf); + OsalMemFree(inputDev); +EXIT: + OsalMemFree(EncoderDrv); + return HDF_FAILURE; +} + +static int32_t HdfEnCoderDriverInit(struct HdfDeviceObject *device) +{ + if (device == NULL) { + HDF_LOGE("%s: param is null", __func__); + return HDF_ERR_INVALID_PARAM; + } + + EncoderCfg *encoderCfg = EncoderConfigInstance(device); + if (encoderCfg == NULL) { + HDF_LOGE("%s: instance encoder config failed", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + int32_t ret = RegisterEncoderDevice(encoderCfg, device); + if (ret != HDF_SUCCESS) { + goto EXIT; + } + + HDF_LOGI("%s: exit succ!", __func__); + return HDF_SUCCESS; + +EXIT: + OsalMemFree(encoderCfg); + return HDF_FAILURE; +} + +static int32_t HdfEnCoderDispatch(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 void HdfEncoderDriverRelease(struct HdfDeviceObject *device) +{ + EncoderDriver *driver = NULL; + InputDevice *inputDev = NULL; + + if (device == NULL || device->priv == NULL) { + HDF_LOGE("%s: param is null", __func__); + return; + } + driver = (EncoderDriver *)device->priv; + inputDev = driver->inputDev; + if (inputDev != NULL) { + UnregisterInputDevice(inputDev); + driver->inputDev = NULL; + } + OsalMemFree(driver); +} + +static int32_t HdfEnCoderDriverBind(struct HdfDeviceObject *device) +{ + if (device == NULL) { + return HDF_ERR_INVALID_PARAM; + } + static struct IDeviceIoService enCoderService = { + .object.objectId = 1, + .Dispatch = HdfEnCoderDispatch, + }; + device->service = &enCoderService; + return HDF_SUCCESS; +} + +struct HdfDriverEntry g_hdfEnCoderEntry = { + .moduleVersion = 1, + .moduleName = "HDF_ENCODER", + .Bind = HdfEnCoderDriverBind, + .Init = HdfEnCoderDriverInit, + .Release = HdfEncoderDriverRelease, +}; + +HDF_INIT(g_hdfEnCoderEntry); diff --git a/model/input/driver/hdf_encoder.h b/model/input/driver/hdf_encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..0456fcfc4efb6cfb63dcb42d718f837e273bd22f --- /dev/null +++ b/model/input/driver/hdf_encoder.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ +#ifndef HDF_ENCODER_H +#define HDF_ENCODER_H + +#include +#include "hdf_input_device_manager.h" +#include "input_config.h" +#include "osal_time.h" +#include "osal_timer.h" + +typedef struct EncoderDriverInfo { + struct HdfDeviceObject *hdfEncoderDev; + uint8_t devType; + EncoderCfg *encoderCfg; + InputDevice *inputDev; + OsalTimer timer; + uint16_t encoderClkPreSta; + uint16_t encoderClkNowSta; + uint16_t encoderDataPreSta; + uint16_t encoderDataNowSta; + uint16_t encoderSWPreSta; + uint16_t encoderSWNowSta +} EncoderDriver; + +#endif \ No newline at end of file diff --git a/model/input/driver/input_config.h b/model/input/driver/input_config.h index e44d400cc9baaa9acdaca5f36ef1e03eed95ce0a..ee25b9f2c503a3d2ba82b59aaf6eb5ff4a8b3f1f 100644 --- a/model/input/driver/input_config.h +++ b/model/input/driver/input_config.h @@ -140,8 +140,17 @@ typedef struct { uint32_t debounceTime; } KeyChipCfg; +typedef struct { + struct HdfDeviceObject *hdfEncoderDev; + uint8_t devType; + uint16_t gpioClk; + uint16_t gpioData; + uint16_t gpioSW; +} EncoderCfg; + int32_t ParseTouchBoardConfig(const struct DeviceResourceNode *node, TouchBoardCfg *config); int32_t ParseTouchChipConfig(const struct DeviceResourceNode *node, TouchChipCfg *config); int32_t ParseKeyConfig(const struct DeviceResourceNode *node, KeyChipCfg *config); +int32_t ParseEncoderConfig(const struct DeviceResourceNode *node, EncoderCfg *config); #endif \ No newline at end of file diff --git a/model/input/driver/input_config_parser.c b/model/input/driver/input_config_parser.c index f6c49ebab1c2fe2f6cf6ecfd14e5dd36475307bf..01bc6524ebe413f334aa06ee4d56a6e63b8de810 100644 --- a/model/input/driver/input_config_parser.c +++ b/model/input/driver/input_config_parser.c @@ -43,7 +43,7 @@ int32_t ParseKeyConfig(const struct DeviceResourceNode *node, KeyChipCfg *config ret = parser->GetUint8(keyNode, "inputType", &config->devType, 0); CHECK_PARSER_RET(ret, "GetUint8"); ret = parser->GetUint16(keyNode, "gpioNum", &config->gpioNum, 0); - CHECK_PARSER_RET(ret, "GetUint32"); + CHECK_PARSER_RET(ret, "GetUint16"); ret = parser->GetUint16(keyNode, "irqFlag", &config->irqFlag, 0); CHECK_PARSER_RET(ret, "GetUint8"); ret = parser->GetUint32(keyNode, "debounceTime", &config->debounceTime, 0); @@ -52,6 +52,33 @@ int32_t ParseKeyConfig(const struct DeviceResourceNode *node, KeyChipCfg *config return HDF_SUCCESS; } +int32_t ParseEncoderConfig(const struct DeviceResourceNode *node, EncoderCfg *config) +{ + if (node == NULL || config == NULL) { + HDF_LOGE("%s: param is null", __func__); + return HDF_FAILURE; + } + + struct DeviceResourceIface *parser = NULL; + parser = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (parser == NULL) { + HDF_LOGE("%s: instance parser failed", __func__); + return HDF_FAILURE; + } + + const struct DeviceResourceNode *encoderNode = node; + int32_t ret = parser->GetUint8(encoderNode, "inputType", &config->devType, 0); + CHECK_PARSER_RET(ret, "GetUint8"); + ret = parser->GetUint16(encoderNode, "gpioClk", &config->gpioClk, 0); + CHECK_PARSER_RET(ret, "GetUint16"); + ret = parser->GetUint16(encoderNode, "gpioDT", &config->gpioData, 0); + CHECK_PARSER_RET(ret, "GetUint16"); + ret = parser->GetUint16(encoderNode, "gpioSW", &config->gpioSW, 0); + CHECK_PARSER_RET(ret, "GetUint16"); + + return HDF_SUCCESS; +} + static int32_t ParseAttr(struct DeviceResourceIface *parser, const struct DeviceResourceNode *attrNode, BoardAttrCfg *attr) {