/******************************************************************************
*
*
* Copyright (C) 2015 NXP Semiconductors
*
* 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.
*
******************************************************************************/
#define LOG_TAG "EseAdaptation"
#include <android/hardware/secure_element/1.0/ISecureElement.h>
#include <android/hardware/secure_element/1.0/ISecureElementHalCallback.h>
#include <android/hardware/secure_element/1.0/types.h>
#include <hwbinder/ProcessState.h>
#include <pthread.h>
#include "EseAdaptation.h"
#include <log/log.h>
using android::hardware::Return;
using android::hardware::Void;
using android::hardware::secure_element::V1_0::ISecureElement;
using android::hardware::secure_element::V1_0::ISecureElementHalCallback;
using android::hardware::hidl_vec;
using android::sp;
using vendor::nxp::nxpese::V1_0::INxpEse;
extern bool nfc_debug_enabled;
extern "C" void GKI_shutdown();
extern void resetConfig();
extern "C" void verify_stack_non_volatile_store();
extern "C" void delete_stack_non_volatile_store(bool forceDelete);
EseAdaptation* EseAdaptation::mpInstance = NULL;
ThreadMutex EseAdaptation::sLock;
ThreadMutex EseAdaptation::sIoctlLock;
sp<INxpEse> EseAdaptation::mHalNxpEse;
sp<ISecureElement> EseAdaptation::mHal;
tHAL_ESE_CBACK* EseAdaptation::mHalCallback = NULL;
tHAL_ESE_DATA_CBACK* EseAdaptation::mHalDataCallback = NULL;
ThreadCondVar EseAdaptation::mHalOpenCompletedEvent;
ThreadCondVar EseAdaptation::mHalCloseCompletedEvent;
#if (NXP_EXTNS == TRUE)
ThreadCondVar EseAdaptation::mHalCoreResetCompletedEvent;
ThreadCondVar EseAdaptation::mHalCoreInitCompletedEvent;
ThreadCondVar EseAdaptation::mHalInitCompletedEvent;
#define SIGNAL_NONE 0
#define SIGNAL_SIGNALED 1
static uint8_t isSignaled = SIGNAL_NONE;
static uint8_t evt_status;
#endif
/*******************************************************************************
**
** Function: EseAdaptation::EseAdaptation()
**
** Description: class constructor
**
** Returns: none
**
*******************************************************************************/
EseAdaptation::EseAdaptation() {
memset(&mSpiHalEntryFuncs, 0, sizeof(mSpiHalEntryFuncs));
}
/*******************************************************************************
**
** Function: EseAdaptation::~EseAdaptation()
**
** Description: class destructor
**
** Returns: none
**
*******************************************************************************/
EseAdaptation::~EseAdaptation() { mpInstance = NULL; }
/*******************************************************************************
**
** Function: EseAdaptation::GetInstance()
**
** Description: access class singleton
**
** Returns: pointer to the singleton object
**
*******************************************************************************/
EseAdaptation& EseAdaptation::GetInstance() {
AutoThreadMutex a(sLock);
if (!mpInstance) mpInstance = new EseAdaptation;
return *mpInstance;
}
/*******************************************************************************
**
** Function: EseAdaptation::Initialize()
**
** Description: class initializer
**
** Returns: none
**
*******************************************************************************/
void EseAdaptation::Initialize() {
const char* func = "EseAdaptation::Initialize";
uint8_t cmd_ese_nxp[] = {0x2F, 0x01, 0x01, 0x01};
ALOGD_IF(nfc_debug_enabled, "%s: enter", func);
mHalCallback = NULL;
ese_nxp_IoctlInOutData_t* pInpOutData;
pInpOutData =
(ese_nxp_IoctlInOutData_t*)malloc(sizeof(ese_nxp_IoctlInOutData_t));
memset(pInpOutData, 0x00, sizeof(ese_nxp_IoctlInOutData_t));
pInpOutData->inp.data.nxpCmd.cmd_len = sizeof(cmd_ese_nxp);
memcpy(pInpOutData->inp.data.nxpCmd.p_cmd, cmd_ese_nxp, sizeof(cmd_ese_nxp));
InitializeHalDeviceContext();
if (pInpOutData != NULL) free(pInpOutData);
ALOGD_IF(nfc_debug_enabled, "%s: exit", func);
}
/*******************************************************************************
**
** Function: EseAdaptation::signal()
**
** Description: signal the CondVar to release the thread that is waiting
**
** Returns: none
**
*******************************************************************************/
void EseAdaptation::signal() { mCondVar.signal(); }
/*******************************************************************************
**
** Function: EseAdaptation::Thread()
**
** Description: Creates work threads
**
** Returns: none
**
*******************************************************************************/
uint32_t EseAdaptation::Thread(uint32_t arg) {
const char* func = "EseAdaptation::Thread";
ALOGD_IF(nfc_debug_enabled, "%s: enter", func);
arg = 0;
{ ThreadCondVar CondVar; }
EseAdaptation::GetInstance().signal();
ALOGD_IF(nfc_debug_enabled, "%s: exit", func);
return 0;
}
/*******************************************************************************
**
** Function: EseAdaptation::GetHalEntryFuncs()
**
** Description: Get the set of HAL entry points.
**
** Returns: Functions pointers for HAL entry points.
**
*******************************************************************************/
tHAL_ESE_ENTRY* EseAdaptation::GetHalEntryFuncs() {
ALOGD_IF(nfc_debug_enabled, "GetHalEntryFuncs: enter");
return &mSpiHalEntryFuncs;
}
/*******************************************************************************
**
** Function: EseAdaptation::InitializeHalDeviceContext
**
** Description: Ask the generic Android HAL to find the Broadcom-specific HAL.
**
** Returns: None.
**
*******************************************************************************/
void EseAdaptation::InitializeHalDeviceContext() {
const char* func = "EseAdaptation::InitializeHalDeviceContext";
ALOGD_IF(nfc_debug_enabled, "%s: enter", func);
ALOGD_IF(nfc_debug_enabled, "%s: INxpEse::tryGetService()", func);
mHalNxpEse = INxpEse::tryGetService();
ALOGD_IF(mHalNxpEse == nullptr, "%s: Failed to retrieve the NXP ESE HAL!", func);
if(mHalNxpEse != nullptr) {
ALOGD_IF(nfc_debug_enabled, "%s: INxpEse::getService() returned %p (%s)",
func, mHalNxpEse.get(),
(mHalNxpEse->isRemote() ? "remote" : "local"));
}
/*Transceive NCI_INIT_CMD*/
ALOGD_IF(nfc_debug_enabled, "%s: exit", func);
}
/*******************************************************************************
**
** Function: EseAdaptation::HalDeviceContextDataCallback
**
** Description: Translate generic Android HAL's callback into Broadcom-specific
** callback function.
**
** Returns: None.
**
*******************************************************************************/
void EseAdaptation::HalDeviceContextDataCallback(uint16_t data_len,
uint8_t* p_data) {
const char* func = "EseAdaptation::HalDeviceContextDataCallback";
ALOGD_IF(nfc_debug_enabled, "%s: len=%u", func, data_len);
if (mHalDataCallback) mHalDataCallback(data_len, p_data);
}
/*******************************************************************************
**
** Function: IoctlCallback
**
** Description: Callback from HAL stub for IOCTL api invoked.
** Output data for IOCTL is sent as argument
**
** Returns: None.
**
*******************************************************************************/
void IoctlCallback(hidl_vec<uint8_t> outputData) {
const char* func = "IoctlCallback";
ese_nxp_ExtnOutputData_t* pOutData =
(ese_nxp_ExtnOutputData_t*)&outputData[0];
ALOGD_IF(nfc_debug_enabled, "%s Ioctl Type=%lu", func,
(unsigned long)pOutData->ioctlType);
EseAdaptation* pAdaptation = (EseAdaptation*)pOutData->context;
/*Output Data from stub->Proxy is copied back to output data
* This data will be sent back to libese*/
memcpy(&pAdaptation->mCurrentIoctlData->out, &outputData[0],
sizeof(ese_nxp_ExtnOutputData_t));
}
/*******************************************************************************
**
** Function: EseAdaptation::HalIoctl
**
** Description: Calls ioctl to the Ese driver.
** If called with a arg value of 0x01 than wired access requested,
** status of the requst would be updated to p_data.
** If called with a arg value of 0x00 than wired access will be
** released, status of the requst would be updated to p_data.
** If called with a arg value of 0x02 than current p61 state would
*be
** updated to p_data.
**
** Returns: -1 or 0.
**
*******************************************************************************/
int EseAdaptation::HalIoctl(long arg, void* p_data) {
const char* func = "EseAdaptation::HalIoctl";
hidl_vec<uint8_t> data;
AutoThreadMutex a(sIoctlLock);
ese_nxp_IoctlInOutData_t* pInpOutData = (ese_nxp_IoctlInOutData_t*)p_data;
ALOGD_IF(nfc_debug_enabled, "%s arg=%ld", func, arg);
pInpOutData->inp.context = &EseAdaptation::GetInstance();
EseAdaptation::GetInstance().mCurrentIoctlData = pInpOutData;
data.setToExternal((uint8_t*)pInpOutData, sizeof(ese_nxp_IoctlInOutData_t));
if (mHalNxpEse != nullptr) mHalNxpEse->ioctl(arg, data, IoctlCallback);
ALOGD_IF(nfc_debug_enabled, "%s Ioctl Completed for Type=%lu", func,
(unsigned long)pInpOutData->out.ioctlType);
return (pInpOutData->out.result);
}
/*******************************************************************************
**
** Function: ThreadMutex::ThreadMutex()
**
** Description: class constructor
**
** Returns: none
**
*******************************************************************************/
ThreadMutex::ThreadMutex() {
pthread_mutexattr_t mutexAttr;
pthread_mutexattr_init(&mutexAttr);
pthread_mutex_init(&mMutex, &mutexAttr);
pthread_mutexattr_destroy(&mutexAttr);
}
/*******************************************************************************
**
** Function: ThreadMutex::~ThreadMutex()
**
** Description: class destructor
**
** Returns: none
**
*******************************************************************************/
ThreadMutex::~ThreadMutex() { pthread_mutex_destroy(&mMutex); }
/*******************************************************************************
**
** Function: ThreadMutex::lock()
**
** Description: lock kthe mutex
**
** Returns: none
**
*******************************************************************************/
void ThreadMutex::lock() { pthread_mutex_lock(&mMutex); }
/*******************************************************************************
**
** Function: ThreadMutex::unblock()
**
** Description: unlock the mutex
**
** Returns: none
**
*******************************************************************************/
void ThreadMutex::unlock() { pthread_mutex_unlock(&mMutex); }
/*******************************************************************************
**
** Function: ThreadCondVar::ThreadCondVar()
**
** Description: class constructor
**
** Returns: none
**
*******************************************************************************/
ThreadCondVar::ThreadCondVar() {
pthread_condattr_t CondAttr;
pthread_condattr_init(&CondAttr);
pthread_cond_init(&mCondVar, &CondAttr);
pthread_condattr_destroy(&CondAttr);
}
/*******************************************************************************
**
** Function: ThreadCondVar::~ThreadCondVar()
**
** Description: class destructor
**
** Returns: none
**
*******************************************************************************/
ThreadCondVar::~ThreadCondVar() { pthread_cond_destroy(&mCondVar); }
/*******************************************************************************
**
** Function: ThreadCondVar::wait()
**
** Description: wait on the mCondVar
**
** Returns: none
**
*******************************************************************************/
void ThreadCondVar::wait() {
pthread_cond_wait(&mCondVar, *this);
pthread_mutex_unlock(*this);
}
/*******************************************************************************
**
** Function: ThreadCondVar::signal()
**
** Description: signal the mCondVar
**
** Returns: none
**
*******************************************************************************/
void ThreadCondVar::signal() {
AutoThreadMutex a(*this);
pthread_cond_signal(&mCondVar);
}
/*******************************************************************************
**
** Function: AutoThreadMutex::AutoThreadMutex()
**
** Description: class constructor, automatically lock the mutex
**
** Returns: none
**
*******************************************************************************/
AutoThreadMutex::AutoThreadMutex(ThreadMutex& m) : mm(m) { mm.lock(); }
/*******************************************************************************
**
** Function: AutoThreadMutex::~AutoThreadMutex()
**
** Description: class destructor, automatically unlock the mutex
**
** Returns: none
**
*******************************************************************************/
AutoThreadMutex::~AutoThreadMutex() { mm.unlock(); }