diff options
| author | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
| commit | 8e4bff4cab0ddac6060645b0715210484d02ff40 (patch) | |
| tree | 3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/input/touchscreen/msg2233/mstar_drv_hotknot.c | |
Diffstat (limited to 'drivers/input/touchscreen/msg2233/mstar_drv_hotknot.c')
| -rw-r--r-- | drivers/input/touchscreen/msg2233/mstar_drv_hotknot.c | 848 |
1 files changed, 848 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/msg2233/mstar_drv_hotknot.c b/drivers/input/touchscreen/msg2233/mstar_drv_hotknot.c new file mode 100644 index 00000000..e33da4ee --- /dev/null +++ b/drivers/input/touchscreen/msg2233/mstar_drv_hotknot.c @@ -0,0 +1,848 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2006-2012 MStar Semiconductor, Inc. +// All rights reserved. +// +// Unless otherwise stipulated in writing, any and all information contained +// herein regardless in any format shall remain the sole proprietary of +// MStar Semiconductor Inc. and be kept in strict confidence +// (??MStar Confidential Information??) by the recipient. +// Any unauthorized act including without limitation unauthorized disclosure, +// copying, use, reproduction, sale, distribution, modification, disassembling, +// reverse engineering and compiling of the contents of MStar Confidential +// Information is unlawful and strictly prohibited. MStar hereby reserves the +// rights to any and all damages, losses, costs and expenses resulting therefrom. +// +//////////////////////////////////////////////////////////////////////////////// + +/** + * + * @file mstar_drv_hotknot.c + * + * @brief This file defines the hotknot functions + * + * + */ + +//////////////////////////////////////////////////////////// +/// Included Files +//////////////////////////////////////////////////////////// +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kthread.h> +#include <asm/uaccess.h> +#include "mstar_drv_hotknot.h" +#include "mstar_drv_utility_adaption.h" +#include "mstar_drv_hotknot_queue.h" +#if defined(CONFIG_ENABLE_TOUCH_DRIVER_FOR_MUTUAL_IC) +#include "mstar_drv_mutual_fw_control.h" +#endif //CONFIG_ENABLE_TOUCH_DRIVER_FOR_MUTUAL_IC + +#ifdef CONFIG_ENABLE_HOTKNOT +//////////////////////////////////////////////////////////// +/// Data Types +//////////////////////////////////////////////////////////// + + +/*=============================================================*/ +// GLOBAL VARIABLE DEFINITION +/*=============================================================*/ +u8 g_HotKnotState; +struct mutex g_QMutex; //queue mutex + + + +/*=============================================================*/ +// EXTERN VARIABLE DECLARATION +/*=============================================================*/ +extern struct mutex g_Mutex; +extern struct i2c_client *g_I2cClient; + +extern u32 SLAVE_I2C_ID_DBBUS; +extern u32 SLAVE_I2C_ID_DWI2C; + +extern u16 FIRMWARE_MODE_UNKNOWN_MODE; +extern u16 FIRMWARE_MODE_DEMO_MODE; +extern u16 FIRMWARE_MODE_DEBUG_MODE; +//extern u16 FIRMWARE_MODE_RAW_DATA_MODE; + +extern u16 g_FirmwareMode; + +extern u8 IS_FIRMWARE_DATA_LOG_ENABLED; + +extern u8 g_IsHotknotEnabled; + + +//////////////////////////////////////////////////////////// +/// LOCAL VARIABLE DEFINITION +//////////////////////////////////////////////////////////// +DrvCmd_t * _gDrvCmdStack; +unsigned long _gArgStack; +u8 * _gHKPacket; +u16 _gHKLength; + +static int _gHKFlag = 0; +static DECLARE_WAIT_QUEUE_HEAD(_gHKWaiter); + +#ifdef CONFIG_ENABLE_HOTKNOT_RCV_BLOCKING +static int _gHKRcvFlag = 0; +static int _gHKRcvWaitEnable = 0; +static DECLARE_WAIT_QUEUE_HEAD(_gHKRcvWaiter); +#endif + +static DrvCmd_t * _gCmdIn; +static u8 * _gSndData; +static u8 * _gRcvData; +static u16 * _gFwMode; + + +//////////////////////////////////////////////////////////// +/// Macro +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +/// Function Prototypes +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +/// Function Implementation +//////////////////////////////////////////////////////////// + +u8 _GetCheckSum(u8 *pBuf, int nLen) +{ + s32 nSum = 0; + int i; + for(i=0; i < nLen; i++) + { + nSum += pBuf[i]; + } + return (u8)(-nSum&0xFF); +} + + +void _DebugShowArray(u8 *pBuf, u16 nLen) +{ + int i; + + for(i=0; i < nLen; i++) + { + DBG("%02X ", pBuf[i]); + + if(i%16==15){ + DBG("\n"); + } + } + DBG("\n"); +} + + +int PushHotKnotData(u8 * pBuf, u16 nLength) +{ + int nQRet; + mutex_lock(&g_QMutex); + nQRet = PushQueue(pBuf, nLength); + mutex_unlock(&g_QMutex); + + return nQRet; +} + + +int PopHotKnotData(u8 * pBuf, u16 nLength) +{ + int nQRet; + mutex_lock(&g_QMutex); + nQRet = PopQueue(pBuf, nLength); + mutex_unlock(&g_QMutex); + + return nQRet; +} + + +int ShowHotKnotData(u8 * pBuf, u16 nLength) +{ + int nQRet; + mutex_lock(&g_QMutex); + nQRet = ShowQueue(pBuf, nLength); + mutex_unlock(&g_QMutex); + + return nQRet; +} + + +void _HotKnotRcvInterruptHandler(u8 *pPacket, u16 nLength) //receive hotknot packet in interrupt +{ + u16 nPacketDataLen = 0; + u16 nQPushLen = 0; + + DBG("*** %s() ***\n", __func__); + + if(g_FirmwareMode == FIRMWARE_MODE_DEMO_MODE) + { + nPacketDataLen = (((DemoHotKnotRcvRet_t*)pPacket)->nActualDataLen_H << 8) | (((DemoHotKnotRcvRet_t*)pPacket)->nActualDataLen_L & 0xFF); + nQPushLen = ((((DemoHotKnotRcvRet_t*)pPacket)->szData)[0]&0x7F) + 1; + if(nPacketDataLen >= nQPushLen) + { + if(PushHotKnotData(((DemoHotKnotRcvRet_t*)pPacket)->szData, nQPushLen)<0) + { + DBG("Error: HotKnot# Over push data into queue."); + } +#ifdef CONFIG_ENABLE_HOTKNOT_RCV_BLOCKING + else + { + if(_gHKRcvWaitEnable == 1) + { + _gHKRcvFlag = 1; + DBG("*** wait up receive_wait. ***\n"); + wake_up_interruptible(&_gHKRcvWaiter); + } + } +#endif //CONFIG_ENABLE_HOTKNOT_RCV_BLOCKING + } + else + { + DBG("Error: HotKnot# Receive data error."); + } + } + else if(IS_FIRMWARE_DATA_LOG_ENABLED && (g_FirmwareMode == FIRMWARE_MODE_DEBUG_MODE)) + { + nPacketDataLen = (((DebugHotKnotRcvRet_t*)pPacket)->nActualDataLen_H << 8) | (((DebugHotKnotRcvRet_t*)pPacket)->nActualDataLen_L & 0xFF); + nQPushLen = ((((DemoHotKnotRcvRet_t*)pPacket)->szData)[0]&0x7F) + 1; + + if(nPacketDataLen >= nQPushLen) + { + if(PushHotKnotData(((DebugHotKnotRcvRet_t*)pPacket)->szData, nQPushLen)<0) + { + DBG("Error: HotKnot# Over push data into queue."); + } +#ifdef CONFIG_ENABLE_HOTKNOT_RCV_BLOCKING + else + { + if(_gHKRcvWaitEnable == 1) + { + _gHKRcvFlag = 1; + DBG("*** wait up receive_wait. ***\n"); + wake_up_interruptible(&_gHKRcvWaiter); + } + } +#endif //CONFIG_ENABLE_HOTKNOT_RCV_BLOCKING + } + else + { + DBG("Error: HotKnot# Receive data error."); + } + } +} + + +void ReportHotKnotCmd(u8 *pPacket, u16 nLength) +{ + //DBG("*** %s() ***\n", __func__); + + if(g_HotKnotState == HOTKNOT_TRANS_STATE && pPacket[0] == HOTKNOT_PACKET_ID && pPacket[3] == HOTKNOT_RECEIVE_PACKET_TYPE) + { + _HotKnotRcvInterruptHandler(pPacket, nLength); + } + else if(_gDrvCmdStack!=NULL && _gArgStack!=0) + { + _gHKPacket = pPacket; + _gHKLength = nLength; + + _gHKFlag = 1; + wake_up_interruptible(&_gHKWaiter); + } +} + + +void _HotKnotCmdInterruptHandler(u8 *pPacket, u16 nLength) +{ + //DBG("*** %s() ***\n", __func__); + + if(_gDrvCmdStack->nCmdId == HOTKNOT_CMD) + { + if(g_FirmwareMode == FIRMWARE_MODE_DEMO_MODE) + { + HotKnotCmd_t *pSnd = (HotKnotCmd_t*)_gDrvCmdStack->pSndData; + DemoHotKnotCmdRet_t *pRcv = (DemoHotKnotCmdRet_t*)pPacket; + if(pRcv->nHeader == DEMO_PD_PACKET_ID && pSnd->nInstruction == pRcv->nInstruction) + { + if(pRcv->nResult == RESULT_OK) + { + if(pRcv->nInstruction == READ_PAIR_STATE) + { + g_HotKnotState = HOTKNOT_BEFORE_TRANS_STATE; + ClearQueue(); + } + else if(pRcv->nInstruction == ENTER_TRANSFER_MODE) + { + g_HotKnotState = HOTKNOT_TRANS_STATE; + } + else if(pRcv->nInstruction == EXIT_TRANSFER_MODE) + { + g_HotKnotState = HOTKNOT_AFTER_TRANS_STATE; + } + else if(pRcv->nInstruction == ENTER_SLAVE_MODE) + { + g_HotKnotState = HOTKNOT_NOT_TRANS_STATE; + } + + if(pRcv->nInstruction == ENABLE_HOTKNOT || pRcv->nInstruction == ENTER_MASTER_MODE || pRcv->nInstruction == ENTER_SLAVE_MODE) + { + g_IsHotknotEnabled = 1; + DBG("*** g_IsHotknotEnabled = %d ***\n", g_IsHotknotEnabled); + } + else if(pRcv->nInstruction == DISABLE_HOTKNOT) + { + g_IsHotknotEnabled = 0; + DBG("*** g_IsHotknotEnabled = %d ***\n", g_IsHotknotEnabled); + } + } + + memcpy(_gDrvCmdStack->pRcvData, pPacket, nLength); + //_gDrvCmdStack->nRcvLen = nLength; + *(_gDrvCmdStack->pFwMode) = FIRMWARE_MODE_DEMO_MODE; + } + } + else if(IS_FIRMWARE_DATA_LOG_ENABLED && (g_FirmwareMode == FIRMWARE_MODE_DEBUG_MODE)) + { + HotKnotCmd_t *pSnd = (HotKnotCmd_t*)_gDrvCmdStack->pSndData; + DebugHotKnotCmdRet_t *pRcv = (DebugHotKnotCmdRet_t*)pPacket; + if(pRcv->nHeader == HOTKNOT_PACKET_ID && pSnd->nInstruction == pRcv->nInstruction) + { + if(pRcv->nResult == RESULT_OK) + { + if(pRcv->nInstruction == READ_PAIR_STATE) + { + g_HotKnotState = HOTKNOT_BEFORE_TRANS_STATE; + ClearQueue(); + } + else if(pRcv->nInstruction == ENTER_TRANSFER_MODE) + { + g_HotKnotState = HOTKNOT_TRANS_STATE; + } + else if(pRcv->nInstruction == EXIT_TRANSFER_MODE) + { + g_HotKnotState = HOTKNOT_AFTER_TRANS_STATE; + } + else if(pRcv->nInstruction == ENTER_SLAVE_MODE) + { + g_HotKnotState = HOTKNOT_NOT_TRANS_STATE; + } + + if(pRcv->nInstruction == ENABLE_HOTKNOT || pRcv->nInstruction == ENTER_MASTER_MODE || pRcv->nInstruction == ENTER_SLAVE_MODE) + { + g_IsHotknotEnabled = 1; + DBG("*** g_IsHotknotEnabled = %d ***\n", g_IsHotknotEnabled); + } + else if(pRcv->nInstruction == DISABLE_HOTKNOT) + { + g_IsHotknotEnabled = 0; + DBG("*** g_IsHotknotEnabled = %d ***\n", g_IsHotknotEnabled); + } + } + + memcpy(_gDrvCmdStack->pRcvData, pPacket, nLength); + //_gDrvCmdStack->nRcvLen = nLength; + *(_gDrvCmdStack->pFwMode) = FIRMWARE_MODE_DEBUG_MODE; + } + } + } + else if(_gDrvCmdStack->nCmdId == HOTKNOT_SEND) + { + if(g_FirmwareMode == FIRMWARE_MODE_DEMO_MODE) + { + HotKnotSnd_t *pSnd = (HotKnotSnd_t*)_gDrvCmdStack->pSndData; + DemoHotKnotSndRet_t *pRcv = (DemoHotKnotSndRet_t*)pPacket; + if(pRcv->nHeader == HOTKNOT_PACKET_ID && pRcv->nType == HOTKNOT_PACKET_TYPE && pSnd->nInstruction == pRcv->nInstruction) + { + //kthread_stop(_gHotKnotTask); + memcpy(_gDrvCmdStack->pRcvData, pPacket, nLength); + //_gDrvCmdStack->nRcvLen = nLength; + *(_gDrvCmdStack->pFwMode) = FIRMWARE_MODE_DEMO_MODE; + } + } + else if(IS_FIRMWARE_DATA_LOG_ENABLED && (g_FirmwareMode == FIRMWARE_MODE_DEBUG_MODE)) + { + HotKnotSnd_t *pSnd = (HotKnotSnd_t*)_gDrvCmdStack->pSndData; + DebugHotKnotSndRet_t *pRcv = (DebugHotKnotSndRet_t*)pPacket; + if(pRcv->nHeader == HOTKNOT_PACKET_ID && pRcv->nType == HOTKNOT_PACKET_TYPE && pSnd->nInstruction == pRcv->nInstruction) + { + //kthread_stop(_gHotKnotTask); + memcpy(_gDrvCmdStack->pRcvData, pPacket, nLength); + //_gDrvCmdStack->nRcvLen = nLength; + *(_gDrvCmdStack->pFwMode) = FIRMWARE_MODE_DEBUG_MODE; + } + } + } +} + + +void _HotKnotTimeOutHandler(void) +{ + DBG("*** %s() ***\n", __func__); + + //handle timeout case + if(_gDrvCmdStack->nCmdId == HOTKNOT_CMD) + { + if(g_FirmwareMode == FIRMWARE_MODE_DEMO_MODE) + { + HotKnotSnd_t *pSnd = (HotKnotSnd_t*)_gDrvCmdStack->pSndData; + DemoHotKnotCmdRet_t *pRcv = (DemoHotKnotCmdRet_t*)_gDrvCmdStack->pRcvData; + memset(pRcv, 0xFF, DEMO_PD_PACKET_RET_LEN); + pRcv->nHeader = DEMO_PD_PACKET_ID; + pRcv->nInstruction = pSnd->nInstruction; + pRcv->nResult = RESULT_TIMEOUT; + pRcv->nIdentify = DEMO_PD_PACKET_IDENTIFY; + pRcv->nCheckSum = _GetCheckSum((u8*)pRcv, DEMO_PD_PACKET_RET_LEN-1); + //_gDrvCmdStack->nRcvLen = DEMO_PD_PACKET_RET_LEN; + *(_gDrvCmdStack->pFwMode) = FIRMWARE_MODE_DEMO_MODE; + } + else if(IS_FIRMWARE_DATA_LOG_ENABLED && (g_FirmwareMode == FIRMWARE_MODE_DEBUG_MODE)) + { + HotKnotSnd_t *pSnd = (HotKnotSnd_t*)_gDrvCmdStack->pSndData; + DebugHotKnotCmdRet_t *pRcv = (DebugHotKnotCmdRet_t*)_gDrvCmdStack->pRcvData; + memset(_gDrvCmdStack->pRcvData, 0xFF, MAX_PD_PACKET_RET_LEN); + pRcv->nHeader = HOTKNOT_PACKET_ID; + pRcv->nPacketLen_H = MAX_PD_PACKET_RET_LEN>>8; + pRcv->nPacketLen_L = MAX_PD_PACKET_RET_LEN&0xFF; + pRcv->nType = HOTKNOT_PACKET_TYPE; + pRcv->nInstruction = pSnd->nInstruction; + pRcv->nResult = RESULT_TIMEOUT; + _gDrvCmdStack->pRcvData[MAX_PD_PACKET_RET_LEN-1] = _GetCheckSum((u8*)pRcv, MAX_PD_PACKET_RET_LEN-1); + //_gDrvCmdStack->nRcvLen = MAX_PD_PACKET_RET_LEN; + *(_gDrvCmdStack->pFwMode) = FIRMWARE_MODE_DEBUG_MODE; + } + } + else if(_gDrvCmdStack->nCmdId == HOTKNOT_SEND) + { + if(g_FirmwareMode == FIRMWARE_MODE_DEMO_MODE) + { + HotKnotSnd_t *pSnd = (HotKnotSnd_t*)_gDrvCmdStack->pSndData; + DemoHotKnotSndRet_t *pRcv = (DemoHotKnotSndRet_t*)_gDrvCmdStack->pRcvData; + memset(_gDrvCmdStack->pRcvData, 0, DEMO_HOTKNOT_SEND_RET_LEN); + pRcv->nHeader = HOTKNOT_PACKET_ID; + pRcv->nPacketLen_H = DEMO_HOTKNOT_SEND_RET_LEN>>8; + pRcv->nPacketLen_L = DEMO_HOTKNOT_SEND_RET_LEN&0xFF; + pRcv->nType = HOTKNOT_PACKET_TYPE; + pRcv->nInstruction = pSnd->nInstruction; + pRcv->nResult = RESULT_TIMEOUT; + pRcv->nCheckSum = _GetCheckSum((u8*)pRcv, DEMO_HOTKNOT_SEND_RET_LEN-1); + //_gDrvCmdStack->nRcvLen = DEMO_HOTKNOT_SEND_RET_LEN; + *(_gDrvCmdStack->pFwMode) = FIRMWARE_MODE_DEMO_MODE; + } + else if(IS_FIRMWARE_DATA_LOG_ENABLED && (g_FirmwareMode == FIRMWARE_MODE_DEBUG_MODE)) + { + HotKnotSnd_t *pSnd = (HotKnotSnd_t*)_gDrvCmdStack->pSndData; + DebugHotKnotSndRet_t *pRcv = (DebugHotKnotSndRet_t*)_gDrvCmdStack->pRcvData; + memset(_gDrvCmdStack->pRcvData, 0, DEBUG_HOTKNOT_SEND_RET_LEN); + pRcv->nHeader = HOTKNOT_PACKET_ID; + pRcv->nPacketLen_H = DEBUG_HOTKNOT_SEND_RET_LEN>>8; + pRcv->nPacketLen_L = DEBUG_HOTKNOT_SEND_RET_LEN&0xFF; + pRcv->nType = HOTKNOT_PACKET_TYPE; + pRcv->nInstruction = pSnd->nInstruction; + pRcv->nResult = RESULT_TIMEOUT; + pRcv->nCheckSum = _GetCheckSum((u8*)pRcv, DEBUG_HOTKNOT_SEND_RET_LEN-1); + //_gDrvCmdStack->nRcvLen = DEBUG_HOTKNOT_SEND_RET_LEN; + *(_gDrvCmdStack->pFwMode) = FIRMWARE_MODE_DEBUG_MODE; + } + } +} + + +int _DrvHandleHotKnotCmd(DrvCmd_t *pCmd, unsigned long nArg) +{ + long nRet; + + DBG("*** %s() ***\n", __func__); + + mutex_lock(&g_Mutex); +#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM +#ifdef CONFIG_ENABLE_DMA_IIC + DmaReset(); +#endif //CONFIG_ENABLE_DMA_IIC +#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM + + IicWriteData(SLAVE_I2C_ID_DWI2C, pCmd->pSndData, pCmd->nSndLen); //send HOTKNOT_CMD to fw + + mutex_unlock(&g_Mutex); + + + _gDrvCmdStack = pCmd; + _gArgStack = nArg; + + set_current_state(TASK_INTERRUPTIBLE); + nRet = wait_event_interruptible_timeout(_gHKWaiter, _gHKFlag != 0, pCmd->nTimeOut/1000 * HZ); + _gHKFlag = 0; + + if(nRet == 0) + { + _HotKnotTimeOutHandler(); + } + else + { + _HotKnotCmdInterruptHandler(_gHKPacket, _gHKLength); + } + + return 0; +} + + +void _DrvHandleHotKnotAuth(DrvCmd_t *pCmd) +{ + DBG("*** %s() ***\n", __func__); + + mutex_lock(&g_Mutex); +#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM +#ifdef CONFIG_ENABLE_DMA_IIC + DmaReset(); +#endif //CONFIG_ENABLE_DMA_IIC +#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM + + //for(i=0; i < pCmd->nSndLen; i++) + //{ + // DBG("%02X ", pCmd->pSndData[i]); + //} + + IicWriteData(SLAVE_I2C_ID_DWI2C, pCmd->pSndData, pCmd->nSndLen); + IicReadData(SLAVE_I2C_ID_DWI2C, pCmd->pRcvData, pCmd->nRcvLen); + + //for(i=0; i < pCmd->nRcvLen; i++) + //{ + // DBG("%02X ", pCmd->pRcvData[i]); + //} + + mutex_unlock(&g_Mutex); +} + + +#ifdef CONFIG_ENABLE_HOTKNOT_RCV_BLOCKING +void _DrvHandleHotKnotRcv(DrvCmd_t *pCmd) +{ + u8 nQueueData; + int nDataLen = -1; + long nRet; + DemoHotKnotLibRcvRet_t *pRcv = NULL; + + DBG("*** %s() ***\n", __func__); + + pCmd->nRcvLen = DEMO_HOTKNOT_RECEIVE_RET_LEN; + pRcv = (DemoHotKnotLibRcvRet_t*)pCmd->pRcvData; + memset(pRcv, 0, DEMO_HOTKNOT_RECEIVE_RET_LEN); + pRcv->nHeader = RECEIVE_DATA; + + if(ShowHotKnotData(&nQueueData, 1) <= 0) //check how many bytes to fetch + { + DBG("ShowHotKnotData: No hotknot data in first check.\n"); + } + else + { + nDataLen = PopHotKnotData(pRcv->szData, (nQueueData&0x7F) + 1); + } + + if(nDataLen > 0) + { + pRcv->nActualHotKnotLen_H = nDataLen>>8; + pRcv->nActualHotKnotLen_L = nDataLen&0xFF; + pRcv->nCheckSum = _GetCheckSum((u8*)pRcv, DEMO_HOTKNOT_RECEIVE_RET_LEN-1); + return; + } + + _gHKRcvWaitEnable = 1; //in wait status + DBG("*** _gHKRcvWaitEnable = 1, receive_timeout = %d***\n", pCmd->nTimeOut * HZ/1000); + set_current_state(TASK_INTERRUPTIBLE); + nRet = wait_event_interruptible_timeout(_gHKRcvWaiter, _gHKRcvFlag != 0, pCmd->nTimeOut * HZ/1000); + _gHKRcvWaitEnable = 0; //no wait + DBG("*** _gHKRcvWaitEnable = 0 ***\n"); + _gHKRcvFlag = 0; + + + if(nRet == 0) //timeout + { + DBG("*** receive_timeout ***\n"); + pRcv->nActualHotKnotLen_H = 0; + pRcv->nActualHotKnotLen_L = 0; + pRcv->nCheckSum = _GetCheckSum((u8*)pRcv, DEMO_HOTKNOT_RECEIVE_RET_LEN-1); + } + else + { + DBG("*** receive_get_data ***\n"); + int nDataLen = -1; + if(ShowHotKnotData(&nQueueData, 1) <= 0) //check how many bytes to fetch + { + DBG("ShowHotKnotData: No hotknot data\n"); + } + else + { + nDataLen = PopHotKnotData(pRcv->szData, (nQueueData&0x7F) + 1); + } + + if(nDataLen < 0) + { + pRcv->nActualHotKnotLen_H = 0; + pRcv->nActualHotKnotLen_L = 0; + } + else + { + pRcv->nActualHotKnotLen_H = nDataLen>>8; + pRcv->nActualHotKnotLen_L = nDataLen&0xFF; + } + pRcv->nCheckSum = _GetCheckSum((u8*)pRcv, DEMO_HOTKNOT_RECEIVE_RET_LEN-1); + } +} +#else +void _DrvHandleHotKnotRcv(DrvCmd_t *pCmd) +{ + u8 nQueueData; + int nDataLen = -1; + DemoHotKnotLibRcvRet_t *pRcv = NULL; + + DBG("*** %s() ***\n", __func__); + + pCmd->nRcvLen = DEMO_HOTKNOT_RECEIVE_RET_LEN; + pRcv = (DemoHotKnotLibRcvRet_t*)pCmd->pRcvData; + memset(pRcv, 0, DEMO_HOTKNOT_RECEIVE_RET_LEN); + pRcv->nHeader = RECEIVE_DATA; + + if(ShowHotKnotData(&nQueueData, 1) <= 0) //check how many bytes to fetch + { + DBG("ShowHotKnotData: No hotknot data\n"); + } + else + { + nDataLen = PopHotKnotData(pRcv->szData, (nQueueData&0x7F) + 1); + } + + if(nDataLen < 0) + { + pRcv->nActualHotKnotLen_H = 0; + pRcv->nActualHotKnotLen_L = 0; + } + else + { + pRcv->nActualHotKnotLen_H = nDataLen>>8; + pRcv->nActualHotKnotLen_L = nDataLen&0xFF; + } + pRcv->nCheckSum = _GetCheckSum((u8*)pRcv, DEMO_HOTKNOT_RECEIVE_RET_LEN-1); +} +#endif + + +void _DrvHandleHotKnotGetQueue(DrvCmd_t *pCmd) +{ + DemoHotKnotGetQRet_t *pRcv = NULL; + + DBG("*** %s() ***\n", __func__); + + pCmd->nRcvLen = HOTKNOT_QUEUE_SIZE+6; + pRcv = (DemoHotKnotGetQRet_t*)pCmd->pRcvData; + memset(pRcv, 0, HOTKNOT_QUEUE_SIZE+6); + pRcv->nHeader = GET_QUEUE; + ShowAllQueue(pRcv->szData, &(pRcv->nFront), &(pRcv->nRear)); + pRcv->nCheckSum = _GetCheckSum((u8*)pRcv, HOTKNOT_QUEUE_SIZE+5); +} + + +void _DrvHandleHotKnotSndTest(DrvCmd_t *pCmd) +{ + u16 nQPushLen = 0; + HotKnotSnd_t *pSnd = NULL; + + DBG("*** %s() ***\n", __func__); + + pSnd = (HotKnotSnd_t*)pCmd->pSndData; + nQPushLen = (pSnd->nDataLen_H << 8) | (pSnd->nDataLen_L & 0xFF); + + DBG("nQPushLen = %d\n", nQPushLen); + if(PushHotKnotData(pSnd->szData, nQPushLen)<0) + { + DBG("Error: HotKnot# Over push data into queue."); + } + + //u8 * pShowArray = (u8*)kmalloc(sizeof(u8)* 256, GFP_KERNEL ); + //ShowHotKnotData(pShowArray, 256); //check queue data + //_DebugShowArray(pShowArray, 256); + //kfree(pShowArray); +} + + +/* +static DrvCmd_t* _TransCmdFromUser( unsigned long nArg ) +{ + long nRet; + DrvCmd_t tCmdIn; + DrvCmd_t *pTransCmd = (DrvCmd_t*)kmalloc( sizeof( DrvCmd_t ), GFP_KERNEL ); + + nRet = copy_from_user( &tCmdIn, (void*)nArg, sizeof( DrvCmd_t ) ); + pTransCmd->nCmdId = tCmdIn.nCmdId; + + pTransCmd->nSndLen = tCmdIn.nSndLen; + pTransCmd->pSndData = (u8*)kmalloc(sizeof(u8)*pTransCmd->nSndLen, GFP_KERNEL ); + nRet = copy_from_user( pTransCmd->pSndData, tCmdIn.pSndData, pTransCmd->nSndLen ); + + pTransCmd->nRcvLen = tCmdIn.nRcvLen; + pTransCmd->pRcvData = (u8*)kmalloc(sizeof(u8)*pTransCmd->nRcvLen, GFP_KERNEL ); + + pTransCmd->pFwMode= (u16*)kmalloc(sizeof(u16), GFP_KERNEL ); + pTransCmd->nTimeOut = tCmdIn.nTimeOut; + + return pTransCmd; +} + + +static void _TransCmdToUser( DrvCmd_t *pTransCmd, unsigned long nArg ) +{ + DrvCmd_t tCmdOut; + long nRet; + + nRet = copy_from_user( &tCmdOut, (void*)nArg, sizeof( DrvCmd_t ) ); + nRet = copy_to_user( tCmdOut.pRcvData, pTransCmd->pRcvData, tCmdOut.nRcvLen); + nRet = copy_to_user( tCmdOut.pFwMode, pTransCmd->pFwMode, sizeof(u16)); + + if ( pTransCmd ) + { + kfree( pTransCmd->pSndData ); + kfree( pTransCmd->pRcvData ); + kfree( pTransCmd->pFwMode ); + kfree( pTransCmd ); + } +} +*/ + + +void _ClearHotKnotMem(void) +{ + DBG("*** %s() ***\n", __func__); + + memset(_gCmdIn, 0, sizeof( DrvCmd_t )); + memset(_gSndData, 0, DEBUG_HOTKNOT_SEND_RET_LEN); + memset(_gRcvData, 0, DEBUG_HOTKNOT_RECEIVE_RET_LEN); + memset(_gFwMode, 0, sizeof(u16)); +} + + +static DrvCmd_t* _TransCmdFromUser( unsigned long nArg ) +{ + long nRet; + DrvCmd_t tCmdIn; + DrvCmd_t *pTransCmd; + + _ClearHotKnotMem(); + pTransCmd = (DrvCmd_t *)_gCmdIn; + nRet = copy_from_user( &tCmdIn, (void*)nArg, sizeof( DrvCmd_t ) ); + pTransCmd->nCmdId = tCmdIn.nCmdId; + + pTransCmd->nSndLen = tCmdIn.nSndLen; + pTransCmd->pSndData = _gSndData; + nRet = copy_from_user( pTransCmd->pSndData, tCmdIn.pSndData, pTransCmd->nSndLen ); + + pTransCmd->nRcvLen = tCmdIn.nRcvLen; + pTransCmd->pRcvData = _gRcvData; + + pTransCmd->pFwMode= _gFwMode; + pTransCmd->nTimeOut = tCmdIn.nTimeOut; + + return pTransCmd; +} + + +static void _TransCmdToUser( DrvCmd_t *pTransCmd, unsigned long nArg ) +{ + DrvCmd_t tCmdOut; + long nRet; + + nRet = copy_from_user( &tCmdOut, (void*)nArg, sizeof( DrvCmd_t ) ); + nRet = copy_to_user( tCmdOut.pRcvData, pTransCmd->pRcvData, tCmdOut.nRcvLen); + nRet = copy_to_user( tCmdOut.pFwMode, pTransCmd->pFwMode, sizeof(u16)); +} + + +long HotKnotIoctl( struct file *pFile, unsigned int nCmd, unsigned long nArg ) +{ + long nRet = 0; + + switch ( nCmd ) + { + case HOTKNOT_IOCTL_RUN_CMD: + { + DrvCmd_t *pTransCmd; + + DBG("*** %s() ***\n", __func__); + + pTransCmd = _TransCmdFromUser( nArg ); + + if(pTransCmd->nCmdId == HOTKNOT_CMD || + (pTransCmd->nCmdId == HOTKNOT_SEND && pTransCmd->pSndData[1] == SEND_DATA)) + { + _DrvHandleHotKnotCmd(pTransCmd, nArg); + _TransCmdToUser(_gDrvCmdStack, _gArgStack); + _gDrvCmdStack = NULL; + _gArgStack = 0; + } + else if(pTransCmd->nCmdId == HOTKNOT_AUTH || + (pTransCmd->nCmdId == HOTKNOT_SEND && pTransCmd->pSndData[1] == AUTH_WRITECIPHER)) + { + _DrvHandleHotKnotAuth(pTransCmd); + _TransCmdToUser(pTransCmd, nArg); + } + else if(pTransCmd->nCmdId == HOTKNOT_RECEIVE && pTransCmd->pSndData[1] == RECEIVE_DATA) + { + _DrvHandleHotKnotRcv(pTransCmd); + _TransCmdToUser(pTransCmd, nArg); + } + else if(pTransCmd->nCmdId == HOTKNOT_RECEIVE && pTransCmd->pSndData[1] == GET_QUEUE) + { + _DrvHandleHotKnotGetQueue(pTransCmd); + _TransCmdToUser(pTransCmd, nArg); + } + else if(pTransCmd->nCmdId == HOTKNOT_SEND && pTransCmd->pSndData[1] == SEND_DATA_TEST) + { + _DrvHandleHotKnotSndTest(pTransCmd); + } + } + break; + + case HOTKNOT_IOCTL_QUERY_VENDOR: + { + char szVendorName[30] = "msg28xx"; + + DBG("*** Query vendor name! ***\n"); + //_DebugShowArray(szVendorName,30); + if(copy_to_user((void*)nArg, szVendorName, 30)) + { + DBG("*** Query vendor name failed! ***\n"); + } + } + break; + + default: + nRet = -EINVAL; + break; + } + + return nRet; +} + + +void CreateHotKnotMem() +{ + DBG("*** %s() ***\n", __func__); + + _gCmdIn = (DrvCmd_t*)kmalloc( sizeof( DrvCmd_t ), GFP_KERNEL ); + _gSndData = (u8*)kmalloc(DEBUG_HOTKNOT_SEND_RET_LEN, GFP_KERNEL ); + _gRcvData = (u8*)kmalloc(DEBUG_HOTKNOT_RECEIVE_RET_LEN, GFP_KERNEL ); + _gFwMode= (u16*)kmalloc(sizeof(u16), GFP_KERNEL ); +} + + +void DeleteHotKnotMem() +{ + DBG("*** %s() ***\n", __func__); + + kfree(_gCmdIn); + kfree(_gSndData); + kfree(_gRcvData); + kfree(_gFwMode); +} + +#endif //CONFIG_ENABLE_HOTKNOT) |
