/****************************************************************************** * * Copyright (C) 2017 ST Microelectronics S.A. * * 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 "NfcNciHalWrapper" #include #include #include #include #include "android_logmsg.h" #include "halcore.h" extern void HalCoreCallback(void* context, uint32_t event, const void* d, size_t length); extern bool I2cOpenLayer(void* dev, HAL_CALLBACK callb, HALHANDLE* pHandle); extern void I2cCloseLayer(); typedef struct { struct nfc_nci_device nci_device; // nci_device must be first struct member // below declarations are private variables within HAL nfc_stack_callback_t* p_cback; nfc_stack_data_callback_t* p_data_cback; HALHANDLE hHAL; } st21nfc_dev_t; typedef enum { HAL_WRAPPER_STATE_CLOSED, HAL_WRAPPER_STATE_OPEN, HAL_WRAPPER_STATE_OPEN_CPLT, HAL_WRAPPER_STATE_NFC_ENABLE_ON, HAL_WRAPPER_STATE_READY } hal_wrapper_state_e; static void halWrapperDataCallback(uint16_t data_len, uint8_t* p_data); static void halWrapperCallback(uint8_t event, uint8_t event_status); nfc_stack_callback_t* mHalWrapperCallback = NULL; nfc_stack_data_callback_t* mHalWrapperDataCallback = NULL; hal_wrapper_state_e mHalWrapperState = HAL_WRAPPER_STATE_CLOSED; HALHANDLE mHalHandle = NULL; bool hal_wrapper_open(st21nfc_dev_t* dev, nfc_stack_callback_t* p_cback, nfc_stack_data_callback_t* p_data_cback, HALHANDLE* pHandle) { bool result; STLOG_HAL_D("%s", __func__); mHalWrapperState = HAL_WRAPPER_STATE_OPEN; mHalWrapperCallback = p_cback; mHalWrapperDataCallback = p_data_cback; dev->p_data_cback = halWrapperDataCallback; dev->p_cback = halWrapperCallback; result = I2cOpenLayer(dev, HalCoreCallback, pHandle); if (!result || !(*pHandle)) { return -1; // We are doomed, stop it here, NOW ! } mHalHandle = *pHandle; return 1; } int hal_wrapper_close(int call_cb) { STLOG_HAL_D("%s", __func__); mHalWrapperState = HAL_WRAPPER_STATE_CLOSED; I2cCloseLayer(); if (call_cb) mHalWrapperCallback(HAL_NFC_CLOSE_CPLT_EVT, HAL_NFC_STATUS_OK); return 1; } void halWrapperDataCallback(uint16_t data_len, uint8_t* p_data) { uint8_t propNfcModeSetCmdOn[] = {0x2f, 0x02, 0x02, 0x02, 0x01}; uint8_t coreInitCmd[] = {0x20, 0x01, 0x02, 0x00, 0x00}; STLOG_HAL_D("%s - mHalWrapperState = %d", __func__, mHalWrapperState); switch (mHalWrapperState) { case HAL_WRAPPER_STATE_CLOSED: // 0 break; case HAL_WRAPPER_STATE_OPEN: // 1 // CORE_RESET_NTF if ((p_data[0] == 0x60) && (p_data[1] == 0x00)) { if (p_data[3] == 0x01) { mHalWrapperCallback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_OK); mHalWrapperState = HAL_WRAPPER_STATE_OPEN_CPLT; } else if (p_data[3] == 0xa1) // Loader mode { mHalWrapperCallback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_FAILED); } } else { mHalWrapperDataCallback(data_len, p_data); } break; case HAL_WRAPPER_STATE_OPEN_CPLT: // 2 // CORE_INIT_RSP if ((p_data[0] == 0x40) && (p_data[1] == 0x01)) { } else if ((p_data[0] == 0x60) && (p_data[1] == 0x06)) { STLOG_HAL_D("%s - Sending PROP_NFC_MODE_SET_CMD", __func__); // Send PROP_NFC_MODE_SET_CMD(ON) if (!HalSendDownstreamTimer(mHalHandle, propNfcModeSetCmdOn, sizeof(propNfcModeSetCmdOn), 100)) { STLOG_HAL_E("NFC-NCI HAL: %s HalSendDownstreamTimer failed", __func__); } mHalWrapperState = HAL_WRAPPER_STATE_NFC_ENABLE_ON; } else { mHalWrapperDataCallback(data_len, p_data); } break; case HAL_WRAPPER_STATE_NFC_ENABLE_ON: // 3 // PROP_NFC_MODE_SET_RSP if ((p_data[0] == 0x4f) && (p_data[1] == 0x02)) { // DO nothing: wait for core_reset_ntf or timer timeout } // CORE_RESET_NTF else if ((p_data[0] == 0x60) && (p_data[1] == 0x00)) { // Stop timer HalSendDownstreamStopTimer(mHalHandle); // Send CORE_INIT_CMD STLOG_HAL_D("%s - Sending CORE_INIT_CMD", __func__); if (!HalSendDownstream(mHalHandle, coreInitCmd, sizeof(coreInitCmd))) { STLOG_HAL_E("NFC-NCI HAL: %s SendDownstream failed", __func__); } } // CORE_INIT_RSP else if ((p_data[0] == 0x40) && (p_data[1] == 0x01)) { STLOG_HAL_D("%s - NFC mode enabled", __func__); mHalWrapperState = HAL_WRAPPER_STATE_READY; mHalWrapperDataCallback(data_len, p_data); } break; case HAL_WRAPPER_STATE_READY: mHalWrapperDataCallback(data_len, p_data); break; } } static void halWrapperCallback(uint8_t event, uint8_t event_status) { uint8_t coreInitCmd[] = {0x20, 0x01, 0x02, 0x00, 0x00}; switch (mHalWrapperState) { case HAL_WRAPPER_STATE_CLOSED: break; case HAL_WRAPPER_STATE_OPEN: break; case HAL_WRAPPER_STATE_OPEN_CPLT: break; case HAL_WRAPPER_STATE_NFC_ENABLE_ON: if (event == HAL_WRAPPER_TIMEOUT_EVT) { // timeout // Send CORE_INIT_CMD STLOG_HAL_D("%s - Sending CORE_INIT_CMD", __func__); if (!HalSendDownstream(mHalHandle, coreInitCmd, sizeof(coreInitCmd))) { STLOG_HAL_E("NFC-NCI HAL: %s SendDownstream failed", __func__); } return; } break; case HAL_WRAPPER_STATE_READY: break; default: break; } mHalWrapperCallback(event, event_status); }