blob: 98bdd77b7bb92bf0c466685b9a15bf75754a694f [file] [log] [blame]
/*
* Copyright (C) 2013 SAMSUNG S.LSI
*
* 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 <cutils/properties.h>
#include <errno.h>
#include <string.h>
#include "device.h"
#include "hal.h"
#include "osi.h"
#include "util.h"
#include "config.h"
using namespace android::hardware::nfc::V1_1;
using android::hardware::nfc::V1_1::NfcEvent;
tNFC_HAL_CB nfc_hal_info;
/* START - VTS Replay */
bool sending_nci_packet = false;
/* END - VTS Replay */
/*************************************
* Generic device handling.
*************************************/
bool nfc_stack_cback(nfc_event_t event, nfc_status_t event_status) {
OSI_logt("!");
if (!nfc_hal_info.stack_cback) return false;
nfc_hal_info.stack_cback(event, event_status);
return true;
}
bool nfc_data_callback(tNFC_NCI_PKT* pkt) {
uint8_t* data = (uint8_t*)pkt;
size_t len = NCI_LEN(pkt) + NCI_HDR_SIZE;
OSI_logt("!");
if (!nfc_hal_info.data_cback) return false;
/* START - VTS Replay */
if (((data[0] >> 4) == 4) && (sending_nci_packet == true)) {
OSI_logt("clear sendig_nci_packet");
sending_nci_packet = false;
}
/* END - VTS Replay */
nfc_hal_info.data_cback(len, data);
return true;
}
int nfc_hal_init(void) {
char valueStr[PROPERTY_VALUE_MAX] = {0};
bool data_trace = false;
int trace_level = 0;
int ret;
OSI_set_debug_level(2);
OSI_init();
OSI_logt("enter; ========================================");
/* START - VTS Replay */
sending_nci_packet = false;
/* END - VTS Replay */
/* don't print log at user binary */
ret = property_get("ro.build.type", valueStr, "");
if (!strncmp("user", valueStr, PROPERTY_VALUE_MAX)) {
property_get("ro.debug_level", valueStr, "");
if (strncmp("0x4f4c", valueStr, PROPERTY_VALUE_MAX)) {
trace_level = 2;
data_trace = true;
}
} else {
if (!get_config_int(cfg_name_table[CFG_TRACE_LEVEL], &trace_level))
trace_level = 0;
if (get_config_int(cfg_name_table[CFG_DATA_TRACE], &ret))
if (ret > 0) data_trace = true;
}
OSI_set_debug_level(trace_level);
memset(&nfc_hal_info, 0, sizeof(nfc_hal_info));
// contenxt init
nfc_hal_info.state = HAL_STATE_INIT;
nfc_hal_info.stack_cback = NULL;
nfc_hal_info.data_cback = NULL;
nfc_hal_info.nci_last_pkt = (tNFC_NCI_PKT*)OSI_mem_get(NCI_CTRL_SIZE);
nfc_hal_info.nci_fragment_pkt = NULL;
nfc_hal_info.msg_task = OSI_task_allocate("hal_task", nfc_hal_task);
nfc_hal_info.nci_timer = OSI_timer_allocate("nci_timer");
nfc_hal_info.sleep_timer = OSI_timer_allocate("sleep_timer");
nfc_hal_info.msg_q = OSI_queue_allocate("msg_q");
nfc_hal_info.nci_q = OSI_queue_allocate("nci_q");
setSleepTimeout(SET_SLEEP_TIME_CFG, 5000);
if (!nfc_hal_info.msg_task || !nfc_hal_info.nci_timer ||
!nfc_hal_info.sleep_timer || !nfc_hal_info.msg_q || !nfc_hal_info.nci_q) {
nfc_hal_deinit();
return -EPERM;
}
if (device_init(data_trace)) {
nfc_hal_deinit();
return -EPERM;
}
OSI_logt("succeed;");
return 0;
}
void nfc_hal_deinit(void) {
OSI_logt("enter;");
device_close();
nfc_hal_info.state = HAL_STATE_DEINIT;
OSI_task_kill(nfc_hal_info.msg_task);
nfc_hal_info.stack_cback = NULL;
nfc_hal_info.data_cback = NULL;
OSI_mem_free((tOSI_MEM_HANDLER)nfc_hal_info.nci_last_pkt);
nfc_hal_info.nci_last_pkt = NULL;
OSI_mem_free((tOSI_MEM_HANDLER)nfc_hal_info.nci_fragment_pkt);
nfc_hal_info.nci_fragment_pkt = NULL;
OSI_timer_free(nfc_hal_info.nci_timer);
OSI_timer_free(nfc_hal_info.sleep_timer);
OSI_queue_free(nfc_hal_info.msg_q);
OSI_queue_free(nfc_hal_info.nci_q);
OSI_deinit();
OSI_logt("exit;");
}
int nfc_hal_open(nfc_stack_callback_t* p_cback,
nfc_stack_data_callback_t* p_data_cback) {
tNFC_HAL_MSG* msg;
OSI_logt("enter;");
/* START - VTS */
if (nfc_hal_info.state == HAL_STATE_POSTINIT) {
OSI_logt("SAMSUNG Hal already open");
return 0;
}
/* END - VTS */
/* Initialize HAL */
nfc_hal_init();
if (device_open()) return -EPERM;
if (OSI_OK != OSI_task_run(nfc_hal_info.msg_task)) {
nfc_hal_deinit();
return -EPERM;
}
nfc_hal_info.stack_cback = p_cback;
nfc_hal_info.data_cback = p_data_cback;
nfc_hal_info.state = HAL_STATE_OPEN;
msg = (tNFC_HAL_MSG*)OSI_mem_get(HAL_EVT_SIZE);
if (msg != NULL) {
msg->event = HAL_EVT_OPEN;
OSI_queue_put(nfc_hal_info.msg_q, (void*)msg);
}
OSI_logt("exit;");
return 0;
}
int nfc_hal_close() {
tNFC_HAL_MSG* msg;
OSI_logt("enter;");
/* START - VTS */
if (nfc_hal_info.state == HAL_STATE_CLOSE) {
OSI_logt("SAMSUNG HAL already closed");
return 1; // FAILED
}
/* END - VTS */
msg = (tNFC_HAL_MSG*)OSI_mem_get(HAL_EVT_SIZE);
if (msg != NULL) {
msg->event = HAL_EVT_TERMINATE;
OSI_queue_put(nfc_hal_info.msg_q, (void*)msg);
}
OSI_task_stop(nfc_hal_info.msg_task);
device_sleep();
device_close();
nfc_hal_info.state = HAL_STATE_CLOSE; /* VTS */
nfc_stack_cback(HAL_NFC_CLOSE_CPLT_EVT, HAL_NFC_STATUS_OK);
/* START - For higher than Android-8.0 */
OSI_deinit();
/* END - For higher than Android-8.0 */
OSI_logt("exit;");
return 0;
}
int nfc_hal_write(uint16_t data_len, const uint8_t* p_data) {
tNFC_HAL_MSG* msg;
size_t size = (size_t)data_len;
OSI_logt("enter;");
/* START - VTS Replay */
if ((sending_nci_packet == true) && ((p_data[0] >> 4) == 2)) {
OSI_logt("Don't send NCI");
return size;
}
/* END - VTS Replay */
msg = (tNFC_HAL_MSG*)OSI_mem_get(size + HAL_EVT_SIZE);
if (msg != NULL) {
msg->event = HAL_EVT_WRITE;
memcpy((uint8_t*)&msg->nci_packet, p_data, size);
/* START - VTS Replay */
if ((sending_nci_packet == false) && ((p_data[0] >> 4) == 2))
sending_nci_packet = true;
/* END - VTS Replay */
}
// changed OIS_queue_put() sequence to meet VTS Replay
if (OSI_queue_put(nfc_hal_info.msg_q, (void*)msg) == -1)
sending_nci_packet = false;
OSI_logt("exit;");
return size; /* VTS */
}
int nfc_hal_core_initialized(uint8_t* p_core_init_rsp_params) {
tNFC_HAL_MSG* msg;
size_t size = (size_t)p_core_init_rsp_params[2] + 3;
OSI_logt("enter;");
msg = (tNFC_HAL_MSG*)OSI_mem_get(size + HAL_EVT_SIZE);
if (msg != NULL) {
msg->event = HAL_EVT_CORE_INIT;
memcpy((uint8_t*)&msg->nci_packet, p_core_init_rsp_params, size);
OSI_queue_put(nfc_hal_info.msg_q, (void*)msg);
}
OSI_logt("exit;");
return 0;
}
int nfc_hal_pre_discover() {
OSI_logt("enter;");
/* START - VTS Replay */
/*
tNFC_HAL_MSG *msg;
msg = (tNFC_HAL_MSG *)OSI_mem_get(HAL_EVT_SIZE);
if (msg != NULL) {
msg->event = HAL_EVT_PRE_DISCOVER;
OSI_queue_put(nfc_hal_info.msg_q, (void *)msg);
}
*/
/* END - VTS Replay */
OSI_logt("exit;");
return 0;
}
int nfc_hal_control_granted() {
tNFC_HAL_MSG* msg;
OSI_logt("enter;");
msg = (tNFC_HAL_MSG*)OSI_mem_get(HAL_EVT_SIZE);
if (msg != NULL) {
msg->event = HAL_EVT_CONTROL_GRANTED;
OSI_queue_put(nfc_hal_info.msg_q, (void*)msg);
}
OSI_logt("exit;");
return 0;
}
int nfc_hal_power_cycle() {
OSI_logt("enter;");
/* START - VTS */
tNFC_HAL_MSG* msg;
if (nfc_hal_info.state == HAL_STATE_CLOSE) {
OSI_logt("SAMSUNG Hal already closed, ignoring power cycle");
return NFC_STATUS_FAILED;
}
msg = (tNFC_HAL_MSG*)OSI_mem_get(HAL_EVT_SIZE);
if (msg != NULL) {
msg->event = HAL_EVT_POWER_CYCLE;
OSI_queue_put(nfc_hal_info.msg_q, (void*)msg);
}
/* END - VTS */
OSI_logt("exit;");
return 0;
}
void setSleepTimeout(int option, uint32_t timeout) {
nfc_hal_info.flag &= ~HAL_FLAG_PROP_ONE_TIMER;
nfc_hal_info.cfg.override_timeout = 0;
if (option == SET_SLEEP_TIME_CFG) {
if (!get_config_int(cfg_name_table[CFG_SLEEP_TIMEOUT],
(int*)&nfc_hal_info.cfg.sleep_timeout))
nfc_hal_info.cfg.sleep_timeout = timeout;
} else if (option == SET_SLEEP_TIME_ONCE) {
nfc_hal_info.cfg.override_timeout = timeout;
nfc_hal_info.flag |= HAL_FLAG_PROP_ONE_TIMER;
} else if (option == SET_SLEEP_TIME_FORCE)
nfc_hal_info.cfg.sleep_timeout = timeout;
else
ALOGE("Unknown option: %d", option);
if (nfc_hal_info.flag & HAL_FLAG_PROP_ONE_TIMER)
OSI_logd("Override timeout is %d ms", nfc_hal_info.cfg.override_timeout);
OSI_logd("Sleep timeout is %d ms", nfc_hal_info.cfg.sleep_timeout);
}
#ifdef INFC_1_1
int nfc_hal_factory_reset(void) {
OSI_logt("enter;");
// TO DO impl
OSI_logt("exit;");
return 0;
}
int nfc_hal_closeForPowerOffCase(void) {
OSI_logt("enter;");
// TO DO impl
nfc_hal_close();
OSI_logt("exit;");
return 0;
}
void nfc_hal_getVendorConfig(android::hardware::nfc::V1_1::NfcConfig& config) {
OSI_logt("v1_1 enter;");
const int MAX_CONFIG_STRING_LEN = 260;
unsigned long num = 0;
std::array<uint8_t, MAX_CONFIG_STRING_LEN> buffer;
buffer.fill(0);
long retlen = 0;
memset(&config, 0x00, sizeof(NfcConfig));
config.nfaPollBailOutMode = false;
if (GetNumValue(NAME_ISO_DEP_MAX_TRANSCEIVE, &num, sizeof(num))) {
config.maxIsoDepTransceiveLength = num;
}
if (GetNumValue(NAME_DEFAULT_OFFHOST_ROUTE, &num, sizeof(num))) {
config.defaultOffHostRoute = num;
}
if (GetNumValue(NAME_DEFAULT_NFCF_ROUTE, &num, sizeof(num))) {
config.defaultOffHostRouteFelica = num;
}
if (GetNumValue(NAME_DEFAULT_SYS_CODE_ROUTE, &num, sizeof(num))) {
config.defaultSystemCodeRoute = num;
}
if (GetNumValue(NAME_DEFAULT_SYS_CODE_PWR_STATE, &num, sizeof(num))) {
config.defaultSystemCodePowerState = num;
}
if (GetNumValue(NAME_DEFAULT_ROUTE, &num, sizeof(num))) {
config.defaultRoute = num;
OSI_logt("mDefaultRoute is %d ", (int)num);
}
if (GetByteArrayValue(NAME_DEVICE_HOST_WHITE_LIST, (char*)buffer.data(),
buffer.size(), &retlen)) {
config.hostWhitelist.resize(retlen);
for (int i = 0; i < retlen; i++) config.hostWhitelist[i] = buffer[i];
}
if (GetNumValue(NAME_OFF_HOST_ESE_PIPE_ID, &num, sizeof(num))) {
config.offHostESEPipeId = num;
}
if (GetNumValue(NAME_OFF_HOST_SIM_PIPE_ID, &num, sizeof(num))) {
config.offHostSIMPipeId = num;
}
if (GetByteArrayValue(NAME_NFA_PROPRIETARY_CFG, (char*)buffer.data(),
buffer.size(), &retlen)) {
config.nfaProprietaryCfg.protocol18092Active = (uint8_t)buffer[0];
config.nfaProprietaryCfg.protocolBPrime = (uint8_t)buffer[1];
config.nfaProprietaryCfg.protocolDual = (uint8_t)buffer[2];
config.nfaProprietaryCfg.protocol15693 = (uint8_t)buffer[3];
config.nfaProprietaryCfg.protocolKovio = (uint8_t)buffer[4];
config.nfaProprietaryCfg.protocolMifare = (uint8_t)buffer[5];
config.nfaProprietaryCfg.discoveryPollKovio = (uint8_t)buffer[6];
config.nfaProprietaryCfg.discoveryPollBPrime = (uint8_t)buffer[7];
config.nfaProprietaryCfg.discoveryListenBPrime = (uint8_t)buffer[8];
} else {
memset(&config.nfaProprietaryCfg, 0xFF, sizeof(ProtocolDiscoveryConfig));
}
if ((GetNumValue(NAME_PRESENCE_CHECK_ALGORITHM, &num, sizeof(num))) &&
(num <= 5)) {
config.presenceCheckAlgorithm = (PresenceCheckAlgorithm)num;
}
OSI_logt("exit;");
}
void nfc_hal_getVendorConfig_1_2(
android::hardware::nfc::V1_2::NfcConfig& config) {
OSI_logt("v1_2 enter;");
const int MAX_CONFIG_STRING_LEN = 260;
unsigned long num = 0;
std::array<uint8_t, MAX_CONFIG_STRING_LEN> buffer;
buffer.fill(0);
long retlen = 0;
memset(&config, 0x00, sizeof(android::hardware::nfc::V1_2::NfcConfig));
nfc_hal_getVendorConfig(config.v1_1);
if (GetByteArrayValue(NAME_OFFHOST_ROUTE_UICC, (char*)buffer.data(),
buffer.size(), &retlen)) {
config.offHostRouteUicc.resize(retlen);
for (int i = 0; i < retlen; i++) {
config.offHostRouteUicc[i] = buffer[i];
}
}
if (GetByteArrayValue(NAME_OFFHOST_ROUTE_ESE, (char*)buffer.data(),
buffer.size(), &retlen)) {
config.offHostRouteEse.resize(retlen);
for (int i = 0; i < retlen; i++) {
config.offHostRouteEse[i] = buffer[i];
}
}
if (GetNumValue(NAME_DEFAULT_ISODEP_ROUTE, &num, sizeof(num))) {
config.defaultIsoDepRoute = num;
}
OSI_logt("exit;");
}
#endif