/* * 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 #include #include #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 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 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