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