summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBongsu Jeon <bongsu.jeon@samsung.com>2021-03-11 17:16:21 +0900
committerBongsu Jeon <bongsu.jeon@samsung.com>2021-03-11 19:05:19 +0900
commit2b9e604ec4c08566ec2c4271e047a2468783db21 (patch)
tree32808ffa6f85dc3a71a37834475a3cd8bfe82d95
parentb25d479395ce726ea6d6b562694080fd5d7ae94f (diff)
downloadnfc-2b9e604ec4c08566ec2c4271e047a2468783db21.tar.gz
Initial Samsung's NFC HAL
This is the initial Samsung's AOSP HAL implementation. Change-Id: I9f2183242ef789c47cf278ac78159855c78ce92c
-rw-r--r--1.2/Android.bp26
-rw-r--r--1.2/HalSecNfc.h26
-rw-r--r--1.2/SecNfc.cpp157
-rw-r--r--1.2/SecNfc.h93
-rw-r--r--1.2/SecNfcService.cpp33
-rw-r--r--1.2/android.hardware.nfc@1.2-service.samsung.rc4
-rw-r--r--Android.bp58
-rw-r--r--halimpl/include/config.h105
-rw-r--r--halimpl/include/device.h31
-rw-r--r--halimpl/include/hal.h213
-rw-r--r--halimpl/include/hal_msg.h137
-rw-r--r--halimpl/include/sec_nfc.h26
-rw-r--r--halimpl/include/util.h41
-rw-r--r--halimpl/osi/osi.h348
-rw-r--r--halimpl/osi/osi_common.h140
-rw-r--r--halimpl/osi/osi_main.cc107
-rw-r--r--halimpl/osi/osi_memory.cc249
-rw-r--r--halimpl/osi/osi_task.cc186
-rw-r--r--halimpl/osi/osi_timer.cc263
-rw-r--r--halimpl/src/config.cpp833
-rw-r--r--halimpl/src/device.cc346
-rw-r--r--halimpl/src/hal.cc452
-rw-r--r--halimpl/src/hal_nci.cc211
-rw-r--r--halimpl/src/hal_task.cc447
-rw-r--r--halimpl/src/util.cc265
25 files changed, 4797 insertions, 0 deletions
diff --git a/1.2/Android.bp b/1.2/Android.bp
new file mode 100644
index 0000000..fbd21fe
--- /dev/null
+++ b/1.2/Android.bp
@@ -0,0 +1,26 @@
+cc_binary {
+ name: "android.hardware.nfc@1.2-service.samsung",
+ defaults: ["hidl_defaults"],
+ proprietary: true,
+ init_rc: ["android.hardware.nfc@1.2-service.samsung.rc"],
+ relative_install_path: "hw",
+ srcs: [
+ "SecNfcService.cpp",
+ "SecNfc.cpp",
+ ],
+ cflags: [
+ ],
+ shared_libs: [
+ "nfc_nci_samsung",
+ "android.hardware.nfc@1.0",
+ "android.hardware.nfc@1.1",
+ "android.hardware.nfc@1.2",
+ "libbase",
+ "libcutils",
+ "libhardware",
+ "liblog",
+ "libutils",
+ "libhidlbase",
+ "libcrypto",
+ ],
+}
diff --git a/1.2/HalSecNfc.h b/1.2/HalSecNfc.h
new file mode 100644
index 0000000..33a9146
--- /dev/null
+++ b/1.2/HalSecNfc.h
@@ -0,0 +1,26 @@
+#ifndef __NFC_SEC_HAL__
+#define __NFC_SEC_HAL__
+
+#include <android/hardware/nfc/1.2/INfc.h>
+#include <android/hardware/nfc/1.2/types.h>
+#include <hardware/nfc.h>
+
+using ::android::hardware::nfc::V1_2::NfcConfig;
+
+int nfc_hal_init(void);
+void nfc_hal_deinit(void);
+int nfc_hal_open(nfc_stack_callback_t* p_cback,
+ nfc_stack_data_callback_t* p_data_cback);
+int nfc_hal_write(uint16_t data_len, const uint8_t* p_data);
+int nfc_hal_core_initialized(uint8_t* p_core_init_rsp_params);
+int nfc_hal_pre_discover();
+int nfc_hal_close();
+int nfc_hal_control_granted();
+int nfc_hal_power_cycle();
+
+int nfc_hal_factory_reset(void);
+int nfc_hal_closeForPowerOffCase(void);
+void nfc_hal_getVendorConfig(android::hardware::nfc::V1_1::NfcConfig& config);
+void nfc_hal_getVendorConfig_1_2(NfcConfig& config);
+
+#endif // __NFC_SEC_HAL__
diff --git a/1.2/SecNfc.cpp b/1.2/SecNfc.cpp
new file mode 100644
index 0000000..6eceaa5
--- /dev/null
+++ b/1.2/SecNfc.cpp
@@ -0,0 +1,157 @@
+/******************************************************************************
+ *
+ * Copyright 2018 Samsung
+ *
+ * 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 "SecNfc.h"
+#include <log/log.h>
+#include "HalSecNfc.h"
+
+typedef uint16_t NFCSTATUS; /* Return values */
+#define NFCSTATUS_SUCCESS (0x0000)
+#define NFCSTATUS_OK (NFCSTATUS_SUCCESS)
+
+#define CHK_STATUS(x) \
+ ((x) == NFCSTATUS_SUCCESS) \
+ ? (android::hardware::nfc::V1_0::NfcStatus::OK) \
+ : (android::hardware::nfc::V1_0::NfcStatus::FAILED)
+
+bool nfc_debug_enabled = true;
+
+namespace android {
+namespace hardware {
+namespace nfc {
+namespace V1_2 {
+namespace implementation {
+
+sp<V1_1::INfcClientCallback> Nfc::mCallbackV1_1 = nullptr;
+sp<V1_0::INfcClientCallback> Nfc::mCallbackV1_0 = nullptr;
+
+Return<V1_0::NfcStatus> Nfc::open_1_1(
+ const sp<V1_1::INfcClientCallback>& clientCallback) {
+ ALOGD_IF(nfc_debug_enabled, "SecNfc::open Enter");
+ if (clientCallback == nullptr) {
+ ALOGD_IF(nfc_debug_enabled, "Nfc::open null callback");
+ return V1_0::NfcStatus::FAILED;
+ } else {
+ mCallbackV1_1 = clientCallback;
+ mCallbackV1_1->linkToDeath(this, 0 /*cookie*/);
+ }
+ ALOGD_IF(nfc_debug_enabled, "SecNfc::open Exit");
+ return open(clientCallback);
+}
+
+Return<V1_0::NfcStatus> Nfc::open(
+ const sp<V1_0::INfcClientCallback>& clientCallback) {
+ ALOGD_IF(nfc_debug_enabled, "SecNfc::open Enter");
+ if (clientCallback == nullptr) {
+ ALOGD_IF(nfc_debug_enabled, "Nfc::open null callback");
+ return V1_0::NfcStatus::FAILED;
+ } else {
+ mCallbackV1_0 = clientCallback;
+ mCallbackV1_0->linkToDeath(this, 0 /*cookie*/);
+ }
+ NFCSTATUS status = nfc_hal_open(eventCallback, dataCallback);
+ ALOGD_IF(nfc_debug_enabled, "SecNfc::open Exit");
+ return CHK_STATUS(status);
+}
+
+Return<uint32_t> Nfc::write(const hidl_vec<uint8_t>& data) {
+ hidl_vec<uint8_t> copy = data;
+ return nfc_hal_write(copy.size(), &copy[0]);
+}
+
+Return<V1_0::NfcStatus> Nfc::coreInitialized(const hidl_vec<uint8_t>& data) {
+ hidl_vec<uint8_t> copy = data;
+ NFCSTATUS status = nfc_hal_core_initialized((unsigned char*)&copy[0]);
+ return CHK_STATUS(status);
+}
+
+Return<::android::hardware::nfc::V1_0::NfcStatus> Nfc::prediscover() {
+ NFCSTATUS status = nfc_hal_pre_discover();
+ return CHK_STATUS(status);
+}
+
+Return<V1_0::NfcStatus> Nfc::close() {
+ if (mCallbackV1_1 == nullptr && mCallbackV1_0 == nullptr) {
+ return V1_0::NfcStatus::FAILED;
+ }
+ NFCSTATUS status = nfc_hal_close(); // To-do function Parameter
+
+ if (mCallbackV1_1 != nullptr) {
+ mCallbackV1_1->unlinkToDeath(this);
+ mCallbackV1_1 = nullptr;
+ }
+ if (mCallbackV1_0 != nullptr) {
+ mCallbackV1_0->unlinkToDeath(this);
+ mCallbackV1_0 = nullptr;
+ }
+ return CHK_STATUS(status);
+}
+
+Return<V1_0::NfcStatus> Nfc::controlGranted() {
+ NFCSTATUS status = nfc_hal_control_granted();
+ return CHK_STATUS(status);
+}
+
+Return<V1_0::NfcStatus> Nfc::powerCycle() {
+ NFCSTATUS status = nfc_hal_power_cycle();
+ return CHK_STATUS(status);
+}
+
+// Methods from ::android::hardware::nfc::V1_1::INfc follow.
+Return<void> Nfc::factoryReset() {
+ nfc_hal_factory_reset();
+ return Void();
+}
+
+Return<V1_0::NfcStatus> Nfc::closeForPowerOffCase() {
+ if (mCallbackV1_1 == nullptr && mCallbackV1_0 == nullptr) {
+ return V1_0::NfcStatus::FAILED;
+ }
+
+ NFCSTATUS status = nfc_hal_closeForPowerOffCase();
+
+ if (mCallbackV1_1 != nullptr) {
+ mCallbackV1_1->unlinkToDeath(this);
+ mCallbackV1_1 = nullptr;
+ }
+ if (mCallbackV1_0 != nullptr) {
+ mCallbackV1_0->unlinkToDeath(this);
+ mCallbackV1_0 = nullptr;
+ }
+ return CHK_STATUS(status);
+}
+
+Return<void> Nfc::getConfig(getConfig_cb hidl_cb) {
+ android::hardware::nfc::V1_1::NfcConfig nfcVendorConfig;
+ nfc_hal_getVendorConfig(nfcVendorConfig);
+ hidl_cb(nfcVendorConfig);
+ return Void();
+}
+
+Return<void> Nfc::getConfig_1_2(getConfig_1_2_cb hidl_cb) {
+ NfcConfig nfcVendorConfig;
+ nfc_hal_getVendorConfig_1_2(nfcVendorConfig);
+ hidl_cb(nfcVendorConfig);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_2
+} // namespace nfc
+} // namespace hardware
+} // namespace android
diff --git a/1.2/SecNfc.h b/1.2/SecNfc.h
new file mode 100644
index 0000000..51bbd69
--- /dev/null
+++ b/1.2/SecNfc.h
@@ -0,0 +1,93 @@
+#ifndef ANDROID_HARDWARE_NFC_V1_2_NFC_H
+#define ANDROID_HARDWARE_NFC_V1_2_NFC_H
+
+#include <android/hardware/nfc/1.2/INfc.h>
+#include <android/hardware/nfc/1.2/types.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace nfc {
+namespace V1_2 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::nfc::V1_2::INfc;
+using ::android::hidl::base::V1_0::IBase;
+
+struct Nfc : public V1_2::INfc, public hidl_death_recipient {
+ public:
+ // Methods from ::android::hardware::nfc::V1_0::INfc follow.
+ Return<V1_0::NfcStatus> open(
+ const sp<V1_0::INfcClientCallback>& clientCallback) override;
+ Return<V1_0::NfcStatus> open_1_1(
+ const sp<V1_1::INfcClientCallback>& clientCallback) override;
+ Return<uint32_t> write(const hidl_vec<uint8_t>& data) override;
+ Return<V1_0::NfcStatus> coreInitialized(
+ const hidl_vec<uint8_t>& data) override;
+ Return<V1_0::NfcStatus> prediscover() override;
+ Return<V1_0::NfcStatus> close() override;
+ Return<V1_0::NfcStatus> controlGranted() override;
+ Return<V1_0::NfcStatus> powerCycle() override;
+
+ // Methods from ::android::hardware::nfc::V1_1::INfc follow.
+ Return<void> factoryReset() override;
+ Return<V1_0::NfcStatus> closeForPowerOffCase() override;
+ Return<void> getConfig(getConfig_cb config) override;
+ Return<void> getConfig_1_2(getConfig_1_2_cb config) override;
+
+ static void eventCallback(uint8_t event, uint8_t status) {
+ if (mCallbackV1_1 != nullptr) {
+ auto ret = mCallbackV1_1->sendEvent_1_1((V1_1::NfcEvent)event,
+ (V1_0::NfcStatus)status);
+ if (!ret.isOk()) {
+ ALOGW("failed to send event!!!");
+ }
+ } else if (mCallbackV1_0 != nullptr) {
+ auto ret = mCallbackV1_0->sendEvent((V1_0::NfcEvent)event,
+ (V1_0::NfcStatus)status);
+ if (!ret.isOk()) {
+ ALOGE("failed to send event!!!");
+ }
+ }
+ }
+
+ static void dataCallback(uint16_t data_len, uint8_t* p_data) {
+ hidl_vec<uint8_t> data;
+ data.setToExternal(p_data, data_len);
+ if (mCallbackV1_1 != nullptr) {
+ auto ret = mCallbackV1_1->sendData(data);
+ if (!ret.isOk()) {
+ ALOGW("failed to send data!!!");
+ }
+ } else if (mCallbackV1_0 != nullptr) {
+ auto ret = mCallbackV1_0->sendData(data);
+ if (!ret.isOk()) {
+ ALOGE("failed to send data!!!");
+ }
+ }
+ }
+
+ virtual void serviceDied(uint64_t /*cookie*/, const wp<IBase>& /*who*/) {
+ close();
+ }
+
+ private:
+ static sp<V1_1::INfcClientCallback> mCallbackV1_1;
+ static sp<V1_0::INfcClientCallback> mCallbackV1_0;
+};
+} // namespace implementation
+} // namespace V1_2
+} // namespace nfc
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_NFC_V1_2_NFC_H
diff --git a/1.2/SecNfcService.cpp b/1.2/SecNfcService.cpp
new file mode 100644
index 0000000..fb11228
--- /dev/null
+++ b/1.2/SecNfcService.cpp
@@ -0,0 +1,33 @@
+#define LOG_TAG "secnfc@1.2-service"
+#include <android/hardware/nfc/1.2/INfc.h>
+#include <log/log.h>
+
+#include <hidl/LegacySupport.h>
+#include "HalSecNfc.h"
+#include "SecNfc.h"
+
+// Generated HIDL files
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::nfc::V1_2::INfc;
+using android::hardware::nfc::V1_2::implementation::Nfc;
+
+int main() {
+ ALOGD("SEC NFC HAL Service 1.2 is starting.");
+ sp<INfc> nfc_service = new Nfc();
+
+ configureRpcThreadpool(1, true /*callerWillJoin*/);
+ status_t status = nfc_service->registerAsService();
+ if (status != OK) {
+ LOG_ALWAYS_FATAL("Could not register service for NFC HAL Iface (%d).",
+ status);
+ return -1;
+ }
+
+ ALOGD("NFC service is ready");
+ joinRpcThreadpool();
+ return 1;
+}
diff --git a/1.2/android.hardware.nfc@1.2-service.samsung.rc b/1.2/android.hardware.nfc@1.2-service.samsung.rc
new file mode 100644
index 0000000..c026cde
--- /dev/null
+++ b/1.2/android.hardware.nfc@1.2-service.samsung.rc
@@ -0,0 +1,4 @@
+service nfc_hal_service /vendor/bin/hw/android.hardware.nfc@1.2-service.sec
+ class hal
+ user nfc
+ group nfc
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..4bcd3b8
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,58 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// 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.
+
+cc_library_shared {
+ name: "nfc_nci_samsung",
+ defaults: ["hidl_defaults"],
+ proprietary: true,
+
+ cflags: [
+ "-DBUILDCFG=1",
+ "-DANDROID",
+ "-DNFC_HAL_TARGET=TRUE",
+ "-DNFC_RW_ONLY=TRUE",
+ "-DNFC_SEC_NOT_OPEN_INCLUDED=TRUE",
+ "-DINFC_1_1",
+ ],
+
+ srcs: [
+ "halimpl/osi/*.cc",
+ "halimpl/src/*.cc",
+ "halimpl/src/*.cpp",
+ ],
+
+ local_include_dirs: [
+ "halimpl/include",
+ "halimpl/osi",
+ ],
+ export_include_dirs: [
+ "halimpl/include",
+ "halimpl/osi",
+ ],
+
+ shared_libs: [
+ "android.hardware.nfc@1.0",
+ "android.hardware.nfc@1.1",
+ "android.hardware.nfc@1.2",
+ "libbase",
+ "libcutils",
+ "libhardware",
+ "libhardware_legacy",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ "libcrypto",
+ ],
+}
diff --git a/halimpl/include/config.h b/halimpl/include/config.h
new file mode 100644
index 0000000..cafc4a4
--- /dev/null
+++ b/halimpl/include/config.h
@@ -0,0 +1,105 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * The original Work has been changed by NXP Semiconductors.
+ *
+ * Copyright (C) 2013-2014 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.
+ *
+ ******************************************************************************/
+/******************************************************************************
+ *
+ * The original Work has been changed by Samsung Electronics.
+
+ *
+ * Copyright (C) 2018 Samsung Electronics, System LSI Division
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int GetStrValue(const char* name, char* p_value, unsigned long len); // SLSI
+int GetNumValue(const char* name, void* p_value, unsigned long len); // SLSI
+int GetByteArrayValue(const char* name, char* pValue, long bufflen,
+ long* len); // SLSI
+#if (NFC_SEC_NOT_OPEN_INCLUDED == TRUE)
+void Set_user_prefix(char* field);
+#endif
+
+void resetConfig(void);
+int isConfigModified();
+int updateConfigTimestamp();
+
+#ifdef __cplusplus
+};
+#endif
+#define NAME_MIFARE_READER_ENABLE "MIFARE_READER_ENABLE"
+#define NAME_FW_STORAGE "FW_STORAGE"
+
+#define NAME_ISO_DEP_MAX_TRANSCEIVE "ISO_DEP_MAX_TRANSCEIVE"
+#define NAME_AID_MATCHING_PLATFORM "AID_MATCHING_PLATFORM"
+#define NAME_NFC_DEBUG_ENABLED "NFC_DEBUG_ENABLED"
+#define NAME_RF_STATUS_UPDATE_ENABLE "RF_STATUS_UPDATE_ENABLE"
+#define NAME_DEFAULT_ROUTE "DEFAULT_ROUTE"
+#define NAME_DEFAULT_OFFHOST_ROUTE "DEFAULT_OFFHOST_ROUTE"
+#define NAME_DEFAULT_NFCF_ROUTE "DEFAULT_NFCF_ROUTE"
+#define NAME_DEFAULT_SYS_CODE_ROUTE "DEFAULT_SYS_CODE_ROUTE"
+#define NAME_DEFAULT_SYS_CODE_PWR_STATE "DEFAULT_SYS_CODE_PWR_STATE"
+#define NAME_DEVICE_HOST_WHITE_LIST "DEVICE_HOST_WHITE_LIST"
+#define NAME_OFF_HOST_ESE_PIPE_ID "OFF_HOST_ESE_PIPE_ID"
+#define NAME_OFF_HOST_SIM_PIPE_ID "OFF_HOST_SIM_PIPE_ID"
+#define NAME_NFA_PROPRIETARY_CFG "NFA_PROPRIETARY_CFG"
+#define NAME_PRESENCE_CHECK_ALGORITHM "PRESENCE_CHECK_ALGORITHM"
+
+#define NAME_OFFHOST_ROUTE_ESE "OFFHOST_ROUTE_ESE"
+#define NAME_OFFHOST_ROUTE_UICC "OFFHOST_ROUTE_UICC"
+#define NAME_DEFAULT_ISODEP_ROUTE "DEFAULT_ISODEP_ROUTE"
+
+/* default configuration */
+#define default_storage_location "/data/vendor/nfc"
+
+#endif
diff --git a/halimpl/include/device.h b/halimpl/include/device.h
new file mode 100644
index 0000000..99ec3b6
--- /dev/null
+++ b/halimpl/include/device.h
@@ -0,0 +1,31 @@
+/*
+ * 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 "hal.h"
+#include "osi.h"
+
+int device_init(int data_trace);
+void device_deinit(void);
+int device_open();
+void device_close(void);
+int device_set_mode(eNFC_DEV_MODE mode);
+int device_sleep(void);
+int device_wakeup(void);
+int device_write(uint8_t* data, size_t len);
+int device_read(uint8_t* buffer, size_t len);
+void data_trace(const char* head, int len, uint8_t* p_data);
diff --git a/halimpl/include/hal.h b/halimpl/include/hal.h
new file mode 100644
index 0000000..153cd99
--- /dev/null
+++ b/halimpl/include/hal.h
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ *
+ */
+#ifndef __NFC_SEC_HAL__
+#define __NFC_SEC_HAL__
+
+#include <hardware/nfc.h>
+
+#include "hal_msg.h"
+#include "osi.h"
+
+#include "android/hardware/nfc/1.2/INfc.h"
+#include "android/hardware/nfc/1.2/types.h"
+
+using ::android::hardware::nfc::V1_1::NfcConfig;
+
+#ifndef __bool_true_false_are_defined
+#define __bool_true_false_are_defined
+typedef enum { false, true } bool;
+#endif
+
+/***************************************
+ * DEVICE
+ ***************************************/
+typedef enum {
+ NFC_DEV_MODE_OFF = 0,
+ NFC_DEV_MODE_ON,
+ NFC_DEV_MODE_BOOTLOADER,
+} eNFC_DEV_MODE;
+
+/***************************************
+ * States
+ ***************************************/
+typedef enum {
+ HAL_STATE_INIT,
+ HAL_STATE_DEINIT,
+ HAL_STATE_OPEN,
+ HAL_STATE_VS,
+ HAL_STATE_POSTINIT,
+ HAL_STATE_SERVICE,
+ HAL_STATE_GRANTED,
+ HAL_STATE_CLOSE, /* VTS */
+ HAL_STATE_POWERCYCLE, /* VTS */
+} eHAL_STATE;
+
+/* FW sub-state */
+#define FW_DATA_PAYLOAD_MAX (256)
+
+/* VS sub-state */
+typedef enum {
+ VS_INIT,
+ VS_W4_COMPLETE,
+} eNFC_HAL_VS_STATE;
+
+/***************************************
+ * Structures
+ ***************************************/
+/* VS related */
+
+typedef struct {
+ eNFC_HAL_VS_STATE state;
+} tNFC_HAL_VS_INFO;
+enum {
+ CFG_SLEEP_TIMEOUT = 0,
+ CFG_WAKEUP_DELAY,
+ CFG_NCI_PROP,
+ CFG_POWER_DRIVER,
+ CFG_TRANS_DRIVER,
+ CFG_TRACE_LEVEL,
+ CFG_DATA_TRACE,
+ CFG_FW_CLK_SPEED,
+};
+
+static const char* cfg_name_table[] = {
+ "SLEEP_TIMEOUT", "WAKEUP_DELAY", "NCI_PROP", "POWER_DRIVER",
+ "TRANS_DRIVER", "TRACE_LEVEL", "DATA_TRACE", "FW_CFG_CLK_SPEED",
+};
+
+typedef struct {
+ uint32_t sleep_timeout;
+ uint32_t override_timeout;
+} tNFC_HAL_CONFIG;
+
+/* Granted related */
+#define HAL_GRANT_SEND_NEXT 0x00
+#define HAL_GRANT_WAIT_READ 0x01
+#define HAL_GRANT_FINISH 0x02
+typedef uint8_t(tNFC_HAL_GRANT_CALLBACK)(tNFC_NCI_PKT* pkt);
+
+/* FLAGS */
+#define HAL_FLAG_MASK_USING_TIMER 0x000F
+#define HAL_FLAG_W4_CORE_RESET_RSP 0x0001
+#define HAL_FLAG_W4_CORE_INIT_RSP 0x0002
+
+#define HAL_FLAG_PROP_RESET 0x0010
+#define HAL_FLAG_CLK_SET 0x0020
+#define HAL_FLAG_PROP_ONE_TIMER 0x0040
+
+#define HAL_FLAG_MASK_ALREADY 0x0F00
+#define HAL_FLAG_ALREADY_RESET 0x0100
+#define HAL_FLAG_ALREADY_INIT 0x0200
+
+#define HAL_FLAG_MASK_SYSTEM 0xF000
+#define HAL_FLAG_FORCE_FW_UPDATE 0x1000
+#define HAL_FLAG_NTF_TRNS_ERROR 0x2000
+#define HAL_FLAG_RETRY_TRNS 0x4000
+
+/***************************************
+ * Main information(context block)
+ ***************************************/
+typedef struct {
+ tNFC_HAL_CONFIG cfg;
+ eHAL_STATE state; /* HAL state */
+ tNFC_HAL_VS_INFO vs_info;
+
+ tOSI_TASK_HANDLER msg_task; /* HAL main task */
+ tOSI_QUEUE_HANDLER msg_q;
+ nfc_stack_callback_t* stack_cback; /* Callback for HAL event */
+ nfc_stack_data_callback_t* data_cback; /* Callback for data event */
+ tNFC_NCI_PKT* nci_last_pkt; /* last sent package */
+ tNFC_NCI_PKT* nci_fragment_pkt; /* Control msg flagmentation */
+ tOSI_TIMER_HANDLER nci_timer; /* Timer for NCI message */
+ tOSI_TIMER_HANDLER sleep_timer; /* Timer for NCI message */
+ int trans_dev; /* transport device */
+ int power_dev; /* power device */
+ tOSI_QUEUE_HANDLER nci_q;
+ tNFC_HAL_GRANT_CALLBACK* grant_cback;
+ unsigned int flag;
+ /* START [H16031401] */
+ uint8_t msg_event; /* receiving message event */
+ /* END [H16031401] */
+} tNFC_HAL_CB;
+
+/*************************************
+ * Global
+ *************************************/
+extern tNFC_HAL_CB nfc_hal_info;
+
+/*************************************
+ * NFC HAL API prototype
+ *************************************/
+int nfc_hal_init(void);
+void nfc_hal_deinit(void);
+int nfc_hal_open(nfc_stack_callback_t* p_cback,
+ nfc_stack_data_callback_t* p_data_cback);
+int nfc_hal_write(uint16_t data_len, const uint8_t* p_data);
+int nfc_hal_core_initialized(uint8_t* p_core_init_rsp_params);
+int nfc_hal_pre_discover();
+int nfc_hal_close();
+int nfc_hal_control_granted();
+int nfc_hal_power_cycle();
+// HIDL INfc 1.1
+int nfc_hal_factory_reset(void);
+int nfc_hal_closeForPowerOffCase(void);
+void nfc_hal_getVendorConfig(NfcConfig& config); // To-Do
+
+/*************************************
+ * NFC HAL functions.
+ *************************************/
+bool nfc_stack_cback(nfc_event_t event, nfc_status_t event_status);
+bool nfc_data_callback(tNFC_NCI_PKT* pkt);
+
+void nfc_hal_task(void);
+
+/* START - VTS */
+void nfc_hal_power_sm(tNFC_HAL_MSG* msg);
+/* END - VTS */
+void nfc_hal_grant_sm(tNFC_HAL_MSG* msg);
+void nfc_hal_service_sm(tNFC_HAL_MSG* msg);
+void nfc_hal_vs_sm(tNFC_HAL_MSG* msg);
+void nfc_hal_postinit_sm(tNFC_HAL_MSG* msg);
+void nfc_hal_open_sm(tNFC_HAL_MSG* msg);
+
+void setSleepTimeout(int option, uint32_t timeout);
+
+const char* event_to_string(uint8_t event);
+const char* state_to_string(eHAL_STATE state);
+
+// SM
+void hal_update_sleep_timer(void);
+int __send_to_device(uint8_t* data, size_t len);
+
+// FW
+void fw_force_update(void* param);
+int nfc_fw_send_data(uint8_t* data, int len);
+int fw_read_payload(tNFC_HAL_MSG* msg);
+
+// NCI
+int hal_nci_send(tNFC_NCI_PKT* pkt);
+void hal_nci_send_reset(void);
+void hal_nci_send_prop_fw_cfg(void);
+void hal_nci_send_clearLmrt(void);
+void nci_init_timeout(void* param);
+bool nfc_hal_prehandler(tNFC_NCI_PKT* pkt);
+int nci_read_payload(tNFC_HAL_MSG* msg);
+
+// TRACE
+void sec_nci_analyzer(tNFC_NCI_PKT* pkt);
+
+#endif // __NFC_SEC_HAL__
diff --git a/halimpl/include/hal_msg.h b/halimpl/include/hal_msg.h
new file mode 100644
index 0000000..a886053
--- /dev/null
+++ b/halimpl/include/hal_msg.h
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ *
+ *
+ */
+
+#ifndef __NFC_SEC_HALMSG__
+#define __NFC_SEC_HALMSG__
+
+/***************************************
+ * NCI
+ ***************************************/
+#define HAL_EVT_SIZE 1
+#define NCI_HDR_SIZE 3
+#define NCI_MAX_PAYLOAD 0xFF
+#define NCI_CTRL_SIZE (NCI_HDR_SIZE + NCI_MAX_PAYLOAD)
+
+typedef struct {
+ uint8_t oct0;
+ uint8_t oid;
+ uint8_t len;
+ uint8_t payload[NCI_MAX_PAYLOAD];
+} tNFC_NCI_PKT;
+/* START [181106] Patch for supporting NCI v2.0 */
+// [1. NCI Version Management]
+#define NCI_VER_1_0 0x10
+#define NCI_VER_2_0 0x20
+/* END [181106] Patch for supporting NCI v2.0 */
+#define NCI_MT(x) ((x)->oct0 & 0xE0)
+#define NCI_PBF(x) ((x)->oct0 & 0x10)
+#define NCI_GID(x) ((x)->oct0 & 0x0F)
+#define NCI_OID(x) ((x)->oid & 0x3F)
+#define NCI_LEN(x) ((x)->len)
+#define NCI_PAYLOAD(x) ((x)->payload)
+#define NCI_STATUS(x) (((x)->payload)[0])
+#define NCI_MF_INFO_SIZE 4
+#define NCI_MF_INFO(x) (((x)->payload) + (x)->len - NCI_MF_INFO_SIZE)
+#define NCI_PKT_LEN(x) (NCI_HDR_SIZE + NCI_LEN(x))
+
+#define NCI_MT_DATA 0x00
+#define NCI_MT_CMD 0x20
+#define NCI_MT_RSP 0x40
+#define NCI_MT_NTF 0x60
+
+#define NCI_PBF_LAST 0x00
+#define NCI_PBF_CONTINUE 0x10
+
+#define NCI_GID_CORE 0x00
+#define NCI_GID_RF_MANAGE 0x01
+#define NCI_GID_EE_MANAGE 0x02
+#define NCI_GID_PROP 0x0F
+
+#define NCI_CORE_RESET 0x00
+#define NCI_CORE_INIT 0x01
+
+#define NCI_PROP_AGAIN \
+ 0x01 /* This prop oid is used only for N3 (sleep mode) \ \
+ */
+#define NCI_PROP_FW_CFG 0x28
+#define NCI_PROP_WR_RESET 0x2F
+#define NCI_PROP_SET_SLEEP_TIME 0x1A /* Last updated value: 20160530 */
+
+#define SET_SLEEP_TIME_CFG 0
+#define SET_SLEEP_TIME_ONCE 1
+#define SET_SLEEP_TIME_FORCE 2
+
+#define NCI_STATUS_OK 0x00
+#define NCI_STATUS_E_SYNTAX 0x05
+
+/* START [S15012201] - block flip cover in RF field */
+#define HAL_NFC_STATUS_ERR_TRANSPORT 2
+/* END [S15012201] - block flip cover in RF field */
+
+/* Response Value for Clock Setting. */
+#define NCI_CLOCK_STATUS_SYNTAX_ERROR 0x01
+#define NCI_CLOCK_STATUS_MISMATCHED 0x02
+#define NCI_CLOCK_STATUS_FULL 0x03
+/***************************************
+ * BOOTLOADER
+ ***************************************/
+#define FW_HDR_SIZE 4
+typedef struct {
+ uint8_t type;
+ uint8_t code;
+ uint16_t len;
+ uint8_t payload[NCI_MAX_PAYLOAD + 1];
+} tNFC_FW_PKT;
+#define FW_PAYLOAD(x) ((x)->payload)
+
+/* type */
+typedef enum { FW_MSG_CMD = 0, FW_MSG_RSP, FW_MSG_DATA } eNFC_FW_BLTYPE;
+
+/***************************************
+ * HAL Message
+ ***************************************/
+#define MSG_EVENT_SIZE 1
+typedef struct {
+ uint8_t event;
+ union {
+ tNFC_NCI_PKT nci_packet;
+ tNFC_FW_PKT fw_packet;
+ uint8_t param[NCI_CTRL_SIZE];
+ };
+} tNFC_HAL_MSG;
+
+#define HAL_EVT_OPEN 0x00
+#define HAL_EVT_CORE_INIT 0x01
+#define HAL_EVT_PRE_DISCOVER 0x02
+#define HAL_EVT_WRITE 0x03
+#define HAL_EVT_READ 0x04
+#define HAL_EVT_CONTROL_GRANTED 0x05
+#define HAL_EVT_TERMINATE 0x06
+/* START - VTS */
+#define HAL_EVT_POWER_CYCLE 0x07
+/* END - VTS */
+#define HAL_EVT_COMPLETE 0xF0
+#define HAL_EVT_COMPLETE_FAILED 0xF1
+
+/***************************************
+ * NFC Message
+ ***************************************/
+#define NFC_STATUS_OK 0x00
+#define NFC_STATUS_FAILED 0x01
+
+#endif //__NFC_SEC_HALMSG__
diff --git a/halimpl/include/sec_nfc.h b/halimpl/include/sec_nfc.h
new file mode 100644
index 0000000..8826bed
--- /dev/null
+++ b/halimpl/include/sec_nfc.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ *
+ *
+ */
+
+#define SEC_NFC_DRIVER_NAME "sec-nfc"
+
+/* ioctl */
+#define SEC_NFC_MAGIC 'S'
+#define SEC_NFC_GET_MODE _IOW(SEC_NFC_MAGIC, 0, unsigned int)
+#define SEC_NFC_SET_MODE _IOW(SEC_NFC_MAGIC, 1, unsigned int)
+#define SEC_NFC_SLEEP _IOW(SEC_NFC_MAGIC, 2, unsigned int)
+#define SEC_NFC_WAKEUP _IOW(SEC_NFC_MAGIC, 3, unsigned int)
diff --git a/halimpl/include/util.h b/halimpl/include/util.h
new file mode 100644
index 0000000..5af4a29
--- /dev/null
+++ b/halimpl/include/util.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ *
+ *
+ */
+#ifndef __NFC_SEC_HALUTIL__
+#define __NFC_SEC_HALUTIL__
+
+#include "osi.h"
+
+#ifndef __bool_true_false_are_defined
+#define __bool_true_false_are_defined
+typedef enum { false, true } bool;
+#endif
+
+#define HAL_UTIL_GET_INT_16 0x0001
+
+bool get_config_int(const char* field, int* data);
+int get_config_string(const char* field, char* strBuffer, size_t bufferSize);
+int get_config_count(const char* field);
+int get_hw_rev();
+
+#ifdef NFC_HAL_NCI_TRACE
+#define util_nci_analyzer(x) sec_nci_analyzer(x)
+#else
+#define util_nci_analyzer(x)
+#endif
+
+#endif //__NFC_SEC_HALUTIL__
diff --git a/halimpl/osi/osi.h b/halimpl/osi/osi.h
new file mode 100644
index 0000000..ac29c54
--- /dev/null
+++ b/halimpl/osi/osi.h
@@ -0,0 +1,348 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef OSI_H
+#define OSI_H
+
+/************************************************************************
+** OS Interface
+*************************************************************************/
+#include <osi_common.h>
+
+#include <log/log.h>
+
+/************************************************************************
+** public functions
+*************************************************************************/
+/*
+ * Function OSI_init
+ *
+ * Description This function is called to initialize OSI context.
+ *
+ * Return OSI_FAIL if any problem
+ * OSI_OK if initialization is succeeded.
+ */
+OSI_STATE OSI_init(void);
+
+/*
+ * Function OSI_deinit
+ *
+ * Description This function is called to deinitialize OSI context.
+ *
+ */
+void OSI_deinit(void);
+
+/*
+ * Function OSI_delay
+ *
+ * Description This function is called to delay.
+ *
+ * Parameter timeout(input): ms
+ *
+ * Return
+ *
+ */
+void OSI_delay(uint32_t timeout);
+
+/***************
+ * OSI TASK
+ ***************/
+/*
+ * Function OSI_task_allocate
+ *
+ * Description This function is called to create a new task.
+ *
+ * Parameter task_name(input):
+ * task_entry(input): entry function.
+ *
+ * Return OSI_TASK_HANDLE if allocate is succeeded,
+ * NULL if any problem.
+ */
+tOSI_TASK_HANDLER OSI_task_allocate(const char* task_name,
+ tOSI_TASK_ENTRY task_entry);
+
+/*
+ * Function OSI_task_run
+ *
+ * Description This function is called to create a new task.
+ *
+ * Parameter OSI_TASK_HANDLE(input): target task
+ *
+ * Return OSI_OK if creadtion is succeeded,
+ * OSI_FAIL if any problem.
+ */
+OSI_STATE OSI_task_run(tOSI_TASK_HANDLER task_handler);
+
+/*
+ * Function OSI_task_isRun
+ *
+ * Description Check the task is running or not.
+ *
+ * Parameter task_handler(input): Target task handler to check running
+ *
+ * Return OSI_RUN, on run.
+ * OSI_FAIL, on error.
+ */
+OSI_STATE OSI_task_isRun(tOSI_TASK_HANDLER task_handler);
+
+/*
+ * Function OSI_task_kill
+ *
+ * Description This function is called to kill a task.
+ *
+ * Parameter task_handler(input): Target task handler to kill.
+ *
+ * Return OSI_OK, on success.
+ * other, on error.
+ */
+OSI_STATE OSI_task_kill(tOSI_TASK_HANDLER task_handler);
+
+/*
+ * Function OSI_task_stop
+ *
+ * Description This function is called to stop a task.
+ *
+ * Parameter task_handler(input): Target task handler to kill.
+ *
+ * Return OSI_OK, on success.
+ * other, on error.
+ */
+OSI_STATE OSI_task_stop(tOSI_TASK_HANDLER task_handler);
+
+/*
+ * Function OSI_task_free
+ *
+ * Description This function is called to free a task.
+ *
+ * Parameter task_handler(input): Target task handler to kill.
+ *
+ * Return OSI_OK, on success.
+ * other, on error.
+ */
+OSI_STATE OSI_task_free(tOSI_TASK_HANDLER task_handler);
+
+/*
+ * Function OSI_task_get_handler
+ *
+ * Description This function is called to get handler by task name.
+ *
+ * Parameter name(input): Target name to get handler.
+ *
+ * Return tOSI_TASK_HANDLER, on success.
+ * NULL, on error.
+ */
+tOSI_TASK_HANDLER OSI_task_get_handler(char* name);
+
+/***************
+ * OSI MEMORY
+ ***************/
+/*
+ * Function OSI_mem_get
+ *
+ * Description This function is called to get memeory.
+ *
+ * Parameter size(input): it should be small than OSI_MEM_POLL_SIZE
+ *
+ * Return Memory address if getting is succeeded,
+ * NULL if any problem.
+ */
+tOSI_MEM_HANDLER OSI_mem_get(size_t size);
+
+/*
+ * Function OSI_mem_free
+ *
+ * Description This function is called to free memeory.
+ *
+ * Parameter target(input):
+ *
+ * Return
+ */
+void OSI_mem_free(tOSI_MEM_HANDLER target);
+
+/** queue **/
+/*
+ * Function OSI_queue_allocate
+ *
+ * Description This function is called to get a free queue.
+ * Anyone using OSI can access this message que.
+ *
+ * Parameter name(input): que_name
+ *
+ * Return tOSI_QUEUE_HANDLER if init is succeeded.
+ * NULL if any problem.
+ */
+tOSI_QUEUE_HANDLER OSI_queue_allocate(const char* que_name);
+
+/*
+ * Function OSI_queue_put
+ *
+ * Description This function is called to put data to the queue.
+ *
+ * Parameter que (input): queue handler.
+ * data (input): void * data to put the stack.
+ *
+ * Return number of element in target queue
+ *
+ */
+int OSI_queue_put(tOSI_QUEUE_HANDLER queue, void* p_data);
+
+/*
+ * Function OSI_queue_get
+ *
+ * Description This function is called to get data from the queue.
+ *
+ * Parameter que (input): queue handler.
+ *
+ * Return (void *) the first data in the queue.
+ * NULL if any problem.
+ */
+void* OSI_queue_get(tOSI_QUEUE_HANDLER queue);
+
+/*
+ * Function OSI_queue_get_wait
+ *
+ * Description This function is called to get data from the queue.
+ * If the queue is empty, this function is waiting for
+ * putting data.
+ *
+ * Parameter que (input): queue handler.
+ *
+ * Return (void *) the first data in the queue.
+ * NULL if any problem.
+ */
+void* OSI_queue_get_wait(tOSI_QUEUE_HANDLER target);
+
+/*
+ * Function OSI_queue_free
+ *
+ * Description This function is called to make que free.
+ *
+ * Parameter que (input): queue handler.
+ *
+ * Return void
+ */
+void OSI_queue_free(tOSI_QUEUE_HANDLER target);
+
+/*
+ * Function OSI_queue_get_handler
+ *
+ * Description This function is called to get handler by queue name.
+ *
+ * Parameter name(input): Target name to get handler.
+ *
+ * Return tOSI_QUEUE_HANDLER, on success.
+ * NULL, on error.
+ */
+tOSI_QUEUE_HANDLER OSI_queue_get_handler(const char* name);
+
+/***************
+ * OSI TIMER
+ ***************/
+/*
+ * Function OSI_timer_allocate
+ *
+ * Description This function is called to get a timer.
+ *
+ * Parameter timer_name(input):
+ *
+ * Return 0 if any problem
+ * other if initialization is succeeded.
+ */
+tOSI_TIMER_HANDLER OSI_timer_allocate(const char* timer_name);
+
+/*
+ * Function OSI_timer_start
+ *
+ * Description This function is called to start a timer.
+ *
+ * Parameter timer_handler (input)
+ * timeout (input): time out value. it is millisecond.
+ * callback (input): callback function.
+ *
+ * Return 0 if any problem
+ * other if initialization is succeeded.
+ *
+ */
+int OSI_timer_start(tOSI_TIMER_HANDLER timer, uint32_t timeout,
+ tOSI_TIMER_CALLBACK callback, void* param);
+
+/*
+ * Function OSI_timer_stop
+ *
+ * Description This function is called to stop a timer.
+ *
+ * Parameter timer_handler (input)
+ *
+ * Return
+ *
+ */
+void OSI_timer_stop(tOSI_TIMER_HANDLER timer);
+
+/*
+ * Function OSI_timer_free
+ *
+ * Description This function is called to free a timer.
+ *
+ * Parameter timer_handler (input)
+ *
+ * Return
+ *
+ */
+void OSI_timer_free(tOSI_TIMER_HANDLER timer);
+
+/*
+ * Function OSI_timer_get_handler
+ *
+ * Description This function is called to get timer handler by name.
+ *
+ * Parameter name(input): Target name to get handler.
+ *
+ * Return tOSI_QUEUE_HANDLER, on success.
+ * NULL, on error.
+ */
+tOSI_TIMER_HANDLER OSI_timer_get_handler(char* name);
+
+/***************
+ * OSI DEBUG
+ ***************/
+#define OSI_DEBUG
+extern int osi_debug_level;
+#define OSI_set_debug_level(xx) (osi_debug_level = xx)
+#ifdef OSI_DEBUG
+#define __osi_log(type, ...) (void)ALOG(type, "SecHAL", __VA_ARGS__)
+#define OSI_logt(format, ...) \
+ do { \
+ if (osi_debug_level >= 2) \
+ __osi_log(LOG_INFO, "%s: " format, __func__, ##__VA_ARGS__); \
+ } while (0)
+#define OSI_logd(format, ...) \
+ do { \
+ if (osi_debug_level >= 1) \
+ __osi_log(LOG_DEBUG, "%s: " format, __func__, ##__VA_ARGS__); \
+ } while (0)
+#define OSI_loge(format, ...) \
+ do { \
+ if (osi_debug_level >= 0) \
+ __osi_log(LOG_ERROR, "%s: " format, __func__, ##__VA_ARGS__); \
+ } while (0)
+#else
+#define OSI_logt(...)
+#define OSI_logd(...)
+#define OSI_loge(...)
+#endif
+
+#endif /* OSI_H */
diff --git a/halimpl/osi/osi_common.h b/halimpl/osi/osi_common.h
new file mode 100644
index 0000000..582c669
--- /dev/null
+++ b/halimpl/osi/osi_common.h
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef OSI_COMMON_H
+#define OSI_COMMON_H
+
+/************************************************************************
+** OS Interface common component
+*************************************************************************/
+#include <pthread.h>
+#ifdef ANDROID
+#include <sys/times.h>
+#endif
+
+/************************************************************************
+** Common definition and type
+*************************************************************************/
+/* OSI common */
+// Maximum count of each obejct
+#define OSI_MAX_TASK (3) // main task, read task
+#define OSI_MAX_MEM_POOL (10)
+#define OSI_MAX_QUEUE (2) // main queue, read queue
+#define OSI_MAX_TIMER (2) // fw download timer, nci timer
+
+// Size of each object
+#define OSI_MEM_POOL_SIZE \
+ (259) // for NFC (NCI_MAX_CTRL_SIZE + NCI_MSG_HDR_SIZE + NFC_HAL_EVT_SIZE)
+#define OSI_QUEUE_SIZE (10)
+
+// State
+typedef uint8_t OSI_STATE;
+#define OSI_FAIL 0
+#define OSI_OK 1
+#define OSI_FREE 2
+#define OSI_ALLOCATED 3
+#define OSI_RUN 4
+#define OSI_STOP 5
+
+#define OSI_TIMER_THREAD_FLAG_DETACH 0x01
+
+/************************************************************************
+** Common definition and type, union
+*************************************************************************/
+/* OSI task */
+typedef void (*tOSI_TASK_ENTRY)(void);
+typedef struct {
+ pthread_t task;
+ const char* name;
+ OSI_STATE state;
+ tOSI_TASK_ENTRY task_entry;
+} sOSI_TASK;
+typedef sOSI_TASK*(tOSI_TASK_HANDLER);
+
+/* OSI memory */
+typedef struct {
+ uint8_t buffer[OSI_MEM_POOL_SIZE];
+ OSI_STATE state;
+} sOSI_MEM;
+typedef sOSI_MEM*(tOSI_MEM_HANDLER);
+
+/* OSI queue */
+typedef struct {
+ void* queue[OSI_QUEUE_SIZE];
+ int head;
+ int tail;
+ const char* name;
+ OSI_STATE state;
+ pthread_cond_t cond;
+} sOSI_QUEUE;
+typedef sOSI_QUEUE*(tOSI_QUEUE_HANDLER);
+
+/* OSI timer */
+typedef void (*tOSI_TIMER_CALLBACK)(void* param);
+typedef struct {
+ int32_t exact_time;
+ int32_t init_timeout;
+ int32_t timeout;
+ const char* name;
+ tOSI_TIMER_CALLBACK callback;
+ void* callback_param;
+ OSI_STATE state;
+} sOSI_TIMER;
+typedef sOSI_TIMER*(tOSI_TIMER_HANDLER);
+
+/* OSI Context */
+typedef struct {
+ /* main */
+ pthread_mutex_t mutex;
+
+ /* task */
+ sOSI_TASK task[OSI_MAX_TASK];
+
+/* memory */
+#ifndef OSI_USE_DYNAMIC_BUF
+ sOSI_MEM mem[OSI_MAX_MEM_POOL];
+#else
+ sOSI_MEM* mem[OSI_MAX_MEM_POOL];
+#endif
+ int32_t mem_max_cnt; /* Maximum number of allocated memory pool */
+
+ /* queue */
+ sOSI_QUEUE queue[OSI_MAX_QUEUE];
+ int32_t queue_max_cnt; /* Maximum number of allocated queue */
+
+ /* timer */
+ sOSI_TIMER timer[OSI_MAX_TIMER];
+ pthread_t timer_thread;
+ int32_t usingTimer;
+ unsigned char timer_thread_flag;
+
+ /* log */
+} tOSI_INFO;
+
+/************************************************************************
+** Global variable
+*************************************************************************/
+extern tOSI_INFO osi_info;
+
+/************************************************************************
+** Internal functions
+*************************************************************************/
+void osi_lock();
+void osi_unlock();
+void OSI_timer_update(int32_t tick);
+int32_t OSI_timer_get_current_time();
+#endif
diff --git a/halimpl/osi/osi_main.cc b/halimpl/osi/osi_main.cc
new file mode 100644
index 0000000..9b67265
--- /dev/null
+++ b/halimpl/osi/osi_main.cc
@@ -0,0 +1,107 @@
+/*
+ * 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 <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include "hal.h"
+#include "osi.h"
+
+#include <errno.h>
+#include <time.h>
+
+int osi_debug_level;
+tOSI_INFO osi_info;
+
+OSI_STATE OSI_init(void) {
+ int32_t index;
+
+ memset(&osi_info, 0, sizeof(osi_info));
+
+ /* Initialize lock */
+ pthread_mutex_init(&osi_info.mutex, NULL);
+
+ /* Initialize task information */
+ for (index = 0; index < OSI_MAX_TASK; index++) {
+ osi_info.task[index].state = OSI_FREE;
+ }
+
+ /* Initialize memory information */
+ osi_info.mem_max_cnt = OSI_MAX_MEM_POOL;
+ for (index = 0; index < OSI_MAX_MEM_POOL; index++) {
+#ifdef OSI_USE_DYNAMIC_BUF
+ osi_info.mem[index] = (tOSI_MEM_HANDLER)malloc(OSI_MEM_POOL_SIZE);
+ if (osi_info.mem[index] == NULL) {
+ OSI_loge("%s : maximum conut of buffer is set to %d, (expected: %d)",
+ index, OSI_MAX_MEM_POOL);
+ osi_info.mem_max_cnt = index;
+ break;
+ }
+ osi_info.mem[index]->state = OSI_FREE;
+#else
+ osi_info.mem[index].state = OSI_FREE;
+#endif
+ }
+
+ /* Initialize queue information */
+ osi_info.queue_max_cnt = OSI_MAX_QUEUE;
+ for (index = 0; index < OSI_MAX_QUEUE; index++) {
+ osi_info.queue[index].state = OSI_FREE;
+ osi_info.queue[index].tail = OSI_QUEUE_SIZE;
+ }
+
+ /* Initialize timer information */
+ for (index = 0; index < OSI_MAX_TIMER; index++) {
+ osi_info.timer[index].state = OSI_FREE;
+ osi_info.timer[index].name = NULL;
+ osi_info.timer[index].callback = NULL;
+ osi_info.timer[index].callback_param = NULL;
+ }
+
+ return OSI_OK;
+}
+
+void OSI_deinit() {
+ int index;
+#ifdef OSI_USE_DYNAMIC_BUF
+ for (index = 0; index < osi_info.mem_max_cnt; index++) {
+ if (osi_info.mem[index]) free(osi_info.mem[index]);
+ }
+#endif
+
+ /* deinitialize timer */
+ for (index = 0; index < OSI_MAX_TIMER; index++) {
+ OSI_timer_free(&osi_info.timer[index]);
+ }
+ osi_info.usingTimer = 0;
+}
+
+void osi_lock() { pthread_mutex_lock(&osi_info.mutex); }
+
+void osi_unlock() { pthread_mutex_unlock(&osi_info.mutex); }
+
+void OSI_delay(uint32_t timeout) {
+ struct timespec delay;
+ int err;
+
+ delay.tv_sec = timeout / 1000;
+ delay.tv_nsec = 1000 * 1000 * (timeout % 1000);
+
+ do {
+ err = nanosleep(&delay, &delay);
+ } while (err < 0 && errno == EINTR);
+}
diff --git a/halimpl/osi/osi_memory.cc b/halimpl/osi/osi_memory.cc
new file mode 100644
index 0000000..434afd7
--- /dev/null
+++ b/halimpl/osi/osi_memory.cc
@@ -0,0 +1,249 @@
+/*
+ * 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.
+ *
+ *
+ */
+
+/************************************************************************
+** OS interface for task handling
+*************************************************************************/
+#include <pthread.h>
+#include <sched.h>
+#include <string.h>
+#include "osi.h"
+
+/************************************************************************
+** Internal function prototype
+*************************************************************************/
+
+/************************************************************************
+** Public functions
+*************************************************************************/
+tOSI_MEM_HANDLER OSI_mem_get(size_t size) {
+ tOSI_MEM_HANDLER free_mem = NULL;
+ int index, err_cnt = 3;
+
+ if (size > OSI_MEM_POOL_SIZE) {
+ OSI_loge("%s : memory getting failed. Max size=%d, Requested size=%d",
+ __func__, OSI_MEM_POOL_SIZE, (int)size);
+ return NULL;
+ }
+
+/* Try 3 times to get memory */
+retry_getting:
+
+ osi_lock();
+ for (index = 0; index < osi_info.mem_max_cnt; index++) {
+#ifdef OSI_USE_DYNAMIC_BUF
+ if (osi_info.mem[index]->state == OSI_FREE)
+ free_mem = (tOSI_MEM_HANDLER)osi_info.mem[index];
+#else
+ if (osi_info.mem[index].state == OSI_FREE)
+ free_mem = (tOSI_MEM_HANDLER)&osi_info.mem[index];
+#endif
+ }
+
+ if (free_mem == NULL) {
+ /* Not found free memory handler */
+ OSI_loge("%s : Failed to find free memory pool(max: %d)", __func__,
+ osi_info.mem_max_cnt);
+#ifdef OSI_USE_DYNAMIC_BUF
+ /* get a new buffer */
+ free_mem = osi_info.mem[index] =
+ (tOSI_MEM_HANDLER)malloc(OSI_MEM_POOL_SIZE);
+ if (osi_info.mem[index] != NULL) {
+ osi_info.mem[index]->state = OSI_FREE;
+ osi_info.mem_max_cnt++;
+ OSI_loge("%s : get a new buffer (max: %d)", __func__,
+ osi_info.mem_max_cnt);
+ } else
+#endif
+ if (--err_cnt > 0) {
+ OSI_loge("%s : try %d time(s) more!", __func__, err_cnt + 1);
+ osi_unlock();
+ sched_yield();
+ OSI_delay(20);
+ goto retry_getting;
+ }
+ } else {
+ free_mem->state = OSI_ALLOCATED;
+ memset(free_mem->buffer, 0, OSI_MEM_POOL_SIZE);
+ }
+ osi_unlock();
+
+ return free_mem;
+}
+
+void OSI_mem_free(tOSI_MEM_HANDLER target) {
+ if (!target) return;
+
+ osi_lock();
+ target->state = OSI_FREE;
+ osi_unlock();
+}
+
+tOSI_QUEUE_HANDLER OSI_queue_allocate(const char* que_name) {
+ tOSI_QUEUE_HANDLER free_que = NULL;
+ int index;
+
+ osi_lock();
+ for (index = 0; index < osi_info.queue_max_cnt; index++) {
+ if (osi_info.queue[index].state == OSI_FREE) {
+ if (free_que == NULL)
+ free_que = (tOSI_QUEUE_HANDLER)&osi_info.queue[index];
+ } else {
+ if (osi_info.queue[index].name == NULL) continue;
+
+ if (strcmp((char const*)osi_info.queue[index].name,
+ (char const*)que_name) == 0) {
+ OSI_loge("%s : %s queue is already allocated [%d]", __func__, que_name,
+ index);
+ free_que = NULL;
+ break;
+ }
+ }
+ }
+
+ if (free_que == NULL) {
+ OSI_loge("%s : Failed to find free queue(max: %d)", __func__,
+ OSI_MAX_QUEUE);
+ } else {
+ memset(free_que->queue, 0, OSI_QUEUE_SIZE);
+ free_que->name = que_name;
+ free_que->state = OSI_ALLOCATED;
+ free_que->head = 0;
+ free_que->tail = OSI_QUEUE_SIZE;
+ }
+ osi_unlock();
+
+ return free_que;
+}
+
+int OSI_queue_put(tOSI_QUEUE_HANDLER queue, void* p_data) {
+ int ret;
+
+ osi_lock();
+
+ if (!queue || queue->state != OSI_ALLOCATED) {
+ OSI_loge("%s : queue is not allocated", __func__);
+ return -1;
+ }
+
+ if (queue->head == queue->tail) {
+ OSI_loge("%s : queue is overflower (max: %d)", __func__, OSI_QUEUE_SIZE);
+ } else {
+ queue->queue[queue->head++] = p_data;
+ if (queue->head >= OSI_QUEUE_SIZE) queue->head = 0;
+
+ // pthread_cond_broadcast(&queue->cond);
+ pthread_cond_signal(&queue->cond);
+ }
+
+ ret = (queue->head) - (queue->tail);
+
+ osi_unlock();
+
+ if (ret < 0) ret += OSI_QUEUE_SIZE;
+
+ return ret;
+}
+
+void* queue_get(tOSI_QUEUE_HANDLER queue) {
+ void* data = NULL;
+
+ if (!queue || queue->state != OSI_ALLOCATED) {
+ OSI_loge("%s : queue is not allocated", __func__);
+ return NULL;
+ }
+
+ if (queue->tail + 1 >= OSI_QUEUE_SIZE) {
+ if (queue->head == 0) {
+ // empty
+ // OSI_loge("%s : queue is empty", __func__);
+ return NULL;
+ }
+ } else {
+ if (queue->tail + 1 == queue->head) {
+ // empty
+ // OSI_loge("%s : queue is empty", __func__);
+ return NULL;
+ }
+ }
+
+ queue->tail++;
+ if (queue->tail >= OSI_QUEUE_SIZE) queue->tail = 0;
+ data = queue->queue[queue->tail];
+
+ return data;
+}
+
+void* OSI_queue_get(tOSI_QUEUE_HANDLER queue) {
+ void* data = NULL;
+
+ osi_lock();
+ data = queue_get(queue);
+ osi_unlock();
+
+ return data;
+}
+
+void* OSI_queue_get_wait(tOSI_QUEUE_HANDLER queue) {
+ void* ret;
+
+ osi_lock();
+
+ if (!queue || queue->state != OSI_ALLOCATED) {
+ OSI_loge("%s : queue is not allocated", __func__);
+ return NULL;
+ }
+
+ ret = queue_get(queue);
+ if (ret == NULL) {
+ pthread_cond_wait(&queue->cond, &osi_info.mutex);
+ ret = queue_get(queue);
+ }
+
+ osi_unlock();
+
+ return ret;
+}
+
+void OSI_queue_free(tOSI_QUEUE_HANDLER target) {
+ if (target) {
+ target->name = NULL;
+ target->state = OSI_FREE;
+ }
+}
+
+tOSI_QUEUE_HANDLER OSI_queue_get_handler(const char* name) {
+ tOSI_QUEUE_HANDLER queue = NULL;
+ int index;
+
+ if (name == NULL) return NULL;
+
+ osi_lock();
+ for (index = 0; index < OSI_MAX_QUEUE; index++) {
+ if (osi_info.queue[index].name == NULL) continue;
+
+ if (strcmp((char const*)osi_info.queue[index].name, (char const*)name) ==
+ 0) {
+ queue = (tOSI_QUEUE_HANDLER)&osi_info.queue[index];
+ break;
+ }
+ }
+ osi_unlock();
+
+ return queue;
+}
diff --git a/halimpl/osi/osi_task.cc b/halimpl/osi/osi_task.cc
new file mode 100644
index 0000000..9174b0e
--- /dev/null
+++ b/halimpl/osi/osi_task.cc
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ *
+ *
+ */
+
+/************************************************************************
+** OS interface for task handling
+*************************************************************************/
+#include <pthread.h>
+#include <signal.h>
+#include <string.h>
+#include "osi.h"
+
+/************************************************************************
+** Internal function prototype
+*************************************************************************/
+
+/************************************************************************
+** Public functions
+*************************************************************************/
+void osi_task_entry(void* arg) {
+ tOSI_TASK_ENTRY task_entry = (tOSI_TASK_ENTRY)arg;
+
+ // pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+
+ task_entry();
+ OSI_logt("%s : exit task", __func__);
+
+ pthread_exit(NULL);
+}
+
+tOSI_TASK_HANDLER OSI_task_allocate(const char* task_name,
+ tOSI_TASK_ENTRY task_entry) {
+ tOSI_TASK_HANDLER free_task = NULL;
+ int index;
+
+ /* Find free task */
+ osi_lock();
+ for (index = 0; index < OSI_MAX_TASK; index++) {
+ if (osi_info.task[index].state == OSI_FREE) {
+ if (free_task == NULL)
+ free_task = (tOSI_TASK_HANDLER)&osi_info.task[index];
+ } else {
+ if (osi_info.task[index].name == NULL) continue;
+
+ /* User can't not make same name of task */
+ if (strcmp((char const*)osi_info.task[index].name,
+ (char const*)task_name) == 0) {
+ OSI_loge("%s : %s task is already allocated [%d]", __func__, task_name,
+ index);
+ free_task = NULL;
+ break;
+ }
+ }
+ }
+
+ if (free_task == NULL) {
+ OSI_loge("%s : Failed to find free task(max: %d)", __func__, OSI_MAX_TASK);
+ } else {
+ free_task->state = OSI_ALLOCATED;
+ free_task->name = task_name;
+ free_task->task_entry = task_entry;
+ }
+
+ osi_unlock();
+ return free_task;
+}
+OSI_STATE OSI_task_run(tOSI_TASK_HANDLER task_handler) {
+ pthread_attr_t attr;
+ int ret = OSI_FAIL;
+
+ osi_lock();
+ if (!task_handler) {
+ OSI_loge("%s : task handler is not exist!!", __func__);
+ } else if (task_handler->state != OSI_ALLOCATED) {
+ OSI_loge("%s : task state is not ALLOCATED!! (%d)", __func__,
+ task_handler->state);
+ } else {
+ /* Thread attr configuration */
+ pthread_attr_init(&attr);
+ if (!pthread_create(&(task_handler->task), &attr,
+ (void* (*)(void*))osi_task_entry,
+ (void*)(task_handler->task_entry))) { //
+ task_handler->state = OSI_RUN;
+ ret = OSI_OK;
+ } else {
+ OSI_loge("%s : pthread_create failed(%d), %s", __func__, ret,
+ task_handler->name);
+ }
+ pthread_attr_destroy(&attr);
+ }
+
+ osi_unlock();
+ return ret;
+}
+
+OSI_STATE OSI_task_isRun(tOSI_TASK_HANDLER task_handler) {
+ OSI_STATE ret = OSI_FAIL;
+ osi_lock();
+ if (task_handler && task_handler->state == OSI_RUN) ret = OSI_RUN;
+ osi_unlock();
+ return ret;
+}
+
+OSI_STATE OSI_task_stop(tOSI_TASK_HANDLER task_handler) {
+ OSI_STATE ret = OSI_OK;
+ if (!task_handler) return OSI_OK;
+
+ osi_lock();
+ if (task_handler->state == OSI_RUN) {
+ osi_unlock();
+ // ret = pthread_cancel(task_handler->task);
+ ret = (OSI_STATE)pthread_join(task_handler->task, NULL);
+ osi_lock();
+ }
+
+ task_handler->state = OSI_ALLOCATED;
+ osi_unlock();
+
+ return ret;
+}
+
+OSI_STATE OSI_task_free(tOSI_TASK_HANDLER task_handler) {
+ OSI_STATE ret = OSI_OK;
+
+ OSI_task_stop(task_handler);
+ osi_lock();
+ task_handler->name = NULL;
+ task_handler->state = OSI_FREE;
+ osi_unlock();
+
+ return ret;
+}
+
+OSI_STATE OSI_task_kill(tOSI_TASK_HANDLER task_handler) {
+ OSI_STATE ret = OSI_OK;
+ if (!task_handler) return OSI_OK;
+
+ osi_lock();
+ if (task_handler->state == OSI_RUN) {
+ osi_unlock();
+ // ret = pthread_cancel(task_handler->task);
+ ret = (OSI_STATE)pthread_join(task_handler->task, NULL);
+ osi_lock();
+ }
+
+ task_handler->name = NULL;
+ task_handler->state = OSI_FREE;
+ osi_unlock();
+
+ return ret;
+}
+
+tOSI_TASK_HANDLER OSI_task_get_handler(char* name) {
+ tOSI_TASK_HANDLER task = NULL;
+ int index;
+
+ if (!name) return NULL;
+
+ osi_lock();
+ for (index = 0; index < OSI_MAX_TASK; index++) {
+ if ((char const*)osi_info.task[index].name == NULL) continue;
+
+ if (strcmp((char const*)osi_info.task[index].name, (char const*)name) ==
+ 0) {
+ task = &osi_info.task[index];
+ break;
+ }
+ }
+ osi_unlock();
+
+ return task;
+}
diff --git a/halimpl/osi/osi_timer.cc b/halimpl/osi/osi_timer.cc
new file mode 100644
index 0000000..6d65cab
--- /dev/null
+++ b/halimpl/osi/osi_timer.cc
@@ -0,0 +1,263 @@
+/*
+ * 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.
+ *
+ *
+ */
+
+/************************************************************************
+** OS interface for task handling
+*************************************************************************/
+#include <errno.h>
+#include <pthread.h>
+#include <string.h>
+#include <sys/time.h>
+#include "osi.h"
+
+/************************************************************************
+** Internal function prototype
+*************************************************************************/
+void timer_thread(void);
+
+/************************************************************************
+** Public functions
+*************************************************************************/
+tOSI_TIMER_HANDLER OSI_timer_allocate(const char* timer_name) {
+ tOSI_TIMER_HANDLER free_timer = NULL;
+ int index;
+
+ osi_lock();
+ for (index = 0; index < OSI_MAX_TIMER; index++) {
+ if (osi_info.timer[index].state == OSI_FREE) {
+ if (free_timer == NULL)
+ free_timer = (tOSI_TIMER_HANDLER)&osi_info.timer[index];
+ } else {
+ if ((char const*)osi_info.timer[index].name == NULL) continue;
+
+ if (strcmp((char const*)osi_info.timer[index].name,
+ (char const*)timer_name) == 0) {
+ OSI_loge("%s : %s timer is already allocated [%d]", __func__,
+ timer_name, index);
+ free_timer = NULL;
+ break;
+ }
+ }
+ }
+
+ if (free_timer == NULL) {
+ OSI_loge("%s : Failed to find free timer(max: %d)", __func__,
+ OSI_MAX_TIMER);
+ } else {
+ free_timer->timeout = 0;
+ free_timer->name = timer_name;
+ free_timer->callback = NULL;
+ free_timer->callback_param = NULL;
+ free_timer->state = OSI_ALLOCATED;
+ }
+ osi_unlock();
+
+ return free_timer;
+}
+
+int OSI_timer_start(tOSI_TIMER_HANDLER timer, uint32_t timeout,
+ tOSI_TIMER_CALLBACK callback, void* param) {
+ pthread_attr_t attr;
+ int ret_th;
+
+ if (timer == NULL) {
+ OSI_loge("%s : Invalid parameters", __func__);
+ return 0;
+ } else if (timer->state == OSI_FREE) {
+ OSI_loge("%s : The timer is not allocated", __func__);
+ return 0;
+ } else {
+ osi_lock();
+ OSI_logt("enter,osi_lock");
+ timer->timeout = timeout;
+ timer->exact_time = OSI_timer_get_current_time();
+ timer->init_timeout = timeout - 10;
+ timer->callback = callback;
+ timer->callback_param = param;
+
+ if (timer->state != OSI_RUN) {
+ timer->state = OSI_RUN;
+
+ /* start timer thread */
+ if (osi_info.usingTimer < 1) {
+ osi_info.timer_thread_flag |= OSI_TIMER_THREAD_FLAG_DETACH;
+ //[START] S.LSI - To increase usingTimer prior to timer_thread
+ osi_info.usingTimer++;
+ //[END] S.LSI - To increase usingTimer prior to timer_thread
+ ret_th = pthread_attr_init(&attr);
+ if (ret_th != 0)
+ OSI_loge("%s : Error pthread_attr_init! ,erron: %d", __func__,
+ ret_th);
+
+ OSI_logt("before pthread_create for timer thread");
+ ret_th = pthread_create(&osi_info.timer_thread, &attr,
+ (void* (*)(void*))timer_thread, NULL);
+ OSI_logt("after pthread_create for timer thread");
+ if (ret_th != 0)
+ OSI_loge("%s : Error to create timer_thread! ,erron: %d", __func__,
+ ret_th);
+
+ ret_th = pthread_attr_destroy(&attr);
+ if (ret_th != 0)
+ OSI_loge("%s : Error pthread_arrt_destroy ,erron: %d", __func__,
+ ret_th);
+ } else
+ osi_info.usingTimer++;
+ }
+ OSI_logt("before osi_unlock");
+ osi_unlock();
+ OSI_logt("exit");
+ return timeout;
+ }
+}
+
+void OSI_timer_stop(tOSI_TIMER_HANDLER timer) {
+ if (timer == NULL) {
+ OSI_loge("%s : Invalid parameters", __func__);
+ } else if (timer->state != OSI_RUN) {
+ OSI_logd("%s : This timer is not running", __func__);
+ } else {
+ osi_lock();
+ timer->state = OSI_STOP;
+ osi_info.usingTimer--;
+ if (osi_info.usingTimer <= 0) {
+ /* Cancle pthread_detach */
+ osi_info.timer_thread_flag &= ~OSI_TIMER_THREAD_FLAG_DETACH;
+ osi_unlock();
+ pthread_join(osi_info.timer_thread, NULL);
+ } else
+ osi_unlock();
+ }
+}
+
+void OSI_timer_free(tOSI_TIMER_HANDLER timer) {
+ if (timer) {
+ osi_lock();
+
+ if (timer->state == OSI_RUN) osi_info.usingTimer--;
+
+ timer->state = OSI_FREE;
+ timer->name = NULL;
+ timer->callback = NULL;
+ timer->callback_param = NULL;
+
+ osi_unlock();
+ }
+}
+
+tOSI_TIMER_HANDLER OSI_timer_get_handler(char* name) {
+ tOSI_TIMER_HANDLER timer = NULL;
+ int index;
+
+ if (name == NULL) return NULL;
+
+ osi_lock();
+ for (index = 0; index < OSI_MAX_TIMER; index++) {
+ if ((char const*)osi_info.timer[index].name == NULL) continue;
+
+ if (strcmp((char const*)osi_info.timer[index].name, (char const*)name) ==
+ 0) {
+ timer = &osi_info.timer[index];
+ break;
+ }
+ }
+ osi_unlock();
+
+ return timer;
+}
+
+int32_t OSI_timer_get_current_time() {
+ struct timeval sec;
+ struct tm* now;
+ time_t rawtime;
+
+ gettimeofday(&sec, NULL);
+ time(&rawtime);
+ now = gmtime(&rawtime);
+
+ return (((now->tm_hour * 3600) + (now->tm_min * 60) + (now->tm_sec)) * 1000) +
+ (sec.tv_usec / 1000);
+}
+/************************************************************************
+** Internal function
+*************************************************************************/
+void OSI_timer_update(int32_t tick) {
+ int index;
+
+ osi_lock();
+
+ /* timer is not using */
+ if (osi_info.usingTimer <= 0) {
+ osi_unlock();
+ return;
+ }
+
+ for (index = 0; index < OSI_MAX_TIMER; index++) {
+ if (osi_info.timer[index].state == OSI_RUN) {
+ osi_info.timer[index].timeout -= tick;
+
+ if (osi_info.timer[index].timeout <= 0) {
+ /* START [16051100] - RTCC Patch */
+ if (((OSI_timer_get_current_time() - osi_info.timer[index].exact_time) >
+ osi_info.timer[index].init_timeout) ||
+ (OSI_timer_get_current_time() < osi_info.timer[index].exact_time))
+ /* END [16051100] - RTCC Patch */
+ {
+ osi_info.timer[index].state = OSI_STOP;
+ osi_info.usingTimer--;
+
+ if (osi_info.timer[index].callback != NULL)
+ osi_info.timer[index].callback(
+ osi_info.timer[index].callback_param);
+ } else {
+ osi_info.timer[index].timeout =
+ osi_info.timer[index].init_timeout -
+ (OSI_timer_get_current_time() - osi_info.timer[index].exact_time);
+ }
+ }
+ }
+ }
+ osi_unlock();
+}
+
+void timer_thread(void) {
+ struct timespec delay;
+ int err;
+
+ while (osi_info.usingTimer > 0) {
+ /* delay */
+ // OSI_delay(1);
+ {
+ /* 1ms sleep for nanosleep()*/
+ delay.tv_sec = 0;
+ delay.tv_nsec = 1000 * 1000;
+
+ do {
+ err = nanosleep(&delay, &delay);
+ if (err < 0) OSI_loge("%s:Fail nanosleep", __func__);
+ } while (err < 0 && errno == EINTR);
+ }
+
+ OSI_timer_update(1);
+ }
+
+ if (osi_info.timer_thread_flag & OSI_TIMER_THREAD_FLAG_DETACH)
+ pthread_detach(pthread_self());
+
+ pthread_exit(NULL);
+}
diff --git a/halimpl/src/config.cpp b/halimpl/src/config.cpp
new file mode 100644
index 0000000..f488ed2
--- /dev/null
+++ b/halimpl/src/config.cpp
@@ -0,0 +1,833 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * The original Work has been changed by NXP Semiconductors.
+ *
+ * Copyright (C) 2013-2014 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.
+ *
+ ******************************************************************************/
+/******************************************************************************
+ *
+ * The original Work has been changed by Samsung Electronics.
+
+ *
+ * Copyright (C) 2018 Samsung Electronics, System LSI Division
+ *
+ * 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 <log/log.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <list>
+#include <string>
+#include <vector>
+
+#include <config.h>
+#include <cutils/properties.h>
+
+#include <hal.h>
+
+#if GENERIC_TARGET
+const char alternative_config_path[] = "/data/vendor/nfc/";
+#else
+const char alternative_config_path[] = "";
+#endif
+
+#if 1
+const char* transport_config_paths[] = {"/odm/etc/", "/vendor/etc/", "/etc/"};
+#else
+const char* transport_config_paths[] = {"res/"};
+#endif
+const int transport_config_path_size =
+ (sizeof(transport_config_paths) / sizeof(transport_config_paths[0]));
+
+#define config_name "libnfc-sec-vendor.conf"
+#define extra_config_base "libnfc-sec-vendor"
+#define extra_config_ext ".conf"
+#define IsStringValue 0x80000000
+
+#if (NFC_SEC_NOT_OPEN_INCLUDED == TRUE)
+
+std::string UserPrefix;
+
+extern "C" void Set_user_prefix(char* field) {
+ UserPrefix.erase();
+
+ if (field != NULL) UserPrefix = field;
+}
+#endif
+
+namespace {
+
+size_t readConfigFile(const char* fileName, uint8_t** p_data) {
+ FILE* fd = fopen(fileName, "rb");
+ if (fd == nullptr) return 0;
+
+ fseek(fd, 0L, SEEK_END);
+ const size_t file_size = ftell(fd);
+ rewind(fd);
+
+ uint8_t* buffer = new uint8_t[file_size];
+ size_t read = fread(buffer, file_size, 1, fd);
+ fclose(fd);
+
+ if (read == 1) {
+ *p_data = buffer;
+ return file_size;
+ }
+
+ delete[] buffer;
+ return 0;
+}
+
+} // namespace
+
+using namespace ::std;
+
+class CNfcParam : public string {
+ public:
+ CNfcParam();
+ CNfcParam(const char* name, const string& value);
+ CNfcParam(const char* name, unsigned long value);
+ virtual ~CNfcParam();
+ unsigned long numValue() const { return m_numValue; }
+ const char* str_value() const { return m_str_value.c_str(); }
+ size_t str_len() const { return m_str_value.length(); }
+
+ private:
+ string m_str_value;
+ unsigned long m_numValue;
+};
+
+class CNfcConfig : public vector<const CNfcParam*> {
+ public:
+ virtual ~CNfcConfig();
+ static CNfcConfig& GetInstance();
+ friend void readOptionalConfig(const char* optional);
+
+ bool getValue(const char* name, char* pValue, size_t len) const;
+ bool getValue(const char* name, unsigned long& rValue) const;
+ bool getValue(const char* name, unsigned short& rValue) const;
+ bool getValue(const char* name, char* pValue, long len, long* readlen) const;
+#if (NFC_SEC_NOT_OPEN_INCLUDED == TRUE)
+ const CNfcParam* _find(const char* p_name) const;
+#endif
+ const CNfcParam* find(const char* p_name) const;
+ void clean();
+
+ private:
+ CNfcConfig();
+ bool readConfig(const char* name, bool bResetContent);
+ void moveFromList();
+ void moveToList();
+ void add(const CNfcParam* pParam);
+ list<const CNfcParam*> m_list;
+ bool mValidFile;
+ unsigned long state;
+
+ inline bool Is(unsigned long f) { return (state & f) == f; }
+ inline void Set(unsigned long f) { state |= f; }
+ inline void Reset(unsigned long f) { state &= ~f; }
+};
+
+/*******************************************************************************
+**
+** Function: isPrintable()
+**
+** Description: determine if 'c' is printable
+**
+** Returns: 1, if printable, otherwise 0
+**
+*******************************************************************************/
+inline bool isPrintable(char c) {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') ||
+#if (NFC_SEC_NOT_OPEN_INCLUDED == TRUE)
+ (c == '+') ||
+#endif
+ c == '/' || c == '_' || c == '-' || c == '.';
+}
+
+/*******************************************************************************
+**
+** Function: isDigit()
+**
+** Description: determine if 'c' is numeral digit
+**
+** Returns: true, if numerical digit
+**
+*******************************************************************************/
+inline bool isDigit(char c, int base) {
+ if ('0' <= c && c <= '9') return true;
+ if (base == 16) {
+ if (('A' <= c && c <= 'F') || ('a' <= c && c <= 'f')) return true;
+ }
+ return false;
+}
+
+/*******************************************************************************
+**
+** Function: getDigitValue()
+**
+** Description: return numerical value of a decimal or hex char
+**
+** Returns: numerical value if decimal or hex char, otherwise 0
+**
+*******************************************************************************/
+inline int getDigitValue(char c, int base) {
+ if ('0' <= c && c <= '9') return c - '0';
+ if (base == 16) {
+ if ('A' <= c && c <= 'F')
+ return c - 'A' + 10;
+ else if ('a' <= c && c <= 'f')
+ return c - 'a' + 10;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function: findConfigFilePathFromTransportConfigPaths()
+**
+** Description: find a config file path with a given config name from transport
+** config paths
+**
+** Returns: none
+**
+*******************************************************************************/
+void findConfigFilePathFromTransportConfigPaths(const string& configName,
+ string& filePath) {
+ for (int i = 0; i < transport_config_path_size - 1; i++) {
+ filePath.assign(transport_config_paths[i]);
+ filePath += configName;
+ struct stat file_stat;
+ if (stat(filePath.c_str(), &file_stat) == 0 && S_ISREG(file_stat.st_mode)) {
+ return;
+ }
+ }
+ filePath.assign(transport_config_paths[transport_config_path_size - 1]);
+ filePath += configName;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::readConfig()
+**
+** Description: read Config settings and parse them into a linked list
+** move the element from linked list to a array at the end
+**
+** Returns: 1, if there are any config data, 0 otherwise
+**
+*******************************************************************************/
+bool CNfcConfig::readConfig(const char* name, bool bResetContent) {
+ enum {
+ BEGIN_LINE = 1,
+ TOKEN,
+ STR_VALUE,
+ NUM_VALUE,
+ BEGIN_HEX,
+ BEGIN_QUOTE,
+ END_LINE
+ };
+
+ uint8_t* p_config = nullptr;
+ size_t config_size = readConfigFile(name, &p_config);
+ if (p_config == nullptr) {
+ ALOGE("%s Cannot open config file %s\n", __func__, name);
+ if (bResetContent) {
+ ALOGE("%s Using default value for all settings\n", __func__);
+ mValidFile = false;
+ }
+ return false;
+ }
+
+ string token;
+ string strValue;
+ unsigned long numValue = 0;
+ CNfcParam* pParam = NULL;
+ int i = 0;
+ int base = 0;
+ char c;
+ int bflag = 0;
+ state = BEGIN_LINE;
+
+ mValidFile = true;
+ if (size() > 0) {
+ if (bResetContent)
+ clean();
+ else
+ moveToList();
+ }
+
+ for (size_t offset = 0; offset != config_size; ++offset) {
+ c = p_config[offset];
+ switch (state & 0xff) {
+ case BEGIN_LINE:
+ if (c == '#')
+ state = END_LINE;
+ else if (isPrintable(c)) {
+ i = 0;
+ token.erase();
+ strValue.erase();
+ state = TOKEN;
+ token.push_back(c);
+ }
+ break;
+ case TOKEN:
+ if (c == '=') {
+ token.push_back('\0');
+ state = BEGIN_QUOTE;
+ } else if (isPrintable(c))
+ token.push_back(c);
+ else
+ state = END_LINE;
+ break;
+ case BEGIN_QUOTE:
+ if (c == '"') {
+ state = STR_VALUE;
+ base = 0;
+ } else if (c == '0')
+ state = BEGIN_HEX;
+ else if (isDigit(c, 10)) {
+ state = NUM_VALUE;
+ base = 10;
+ numValue = getDigitValue(c, base);
+ i = 0;
+ } else if (c == '{') {
+ state = NUM_VALUE;
+ bflag = 1;
+ base = 16;
+ i = 0;
+ Set(IsStringValue);
+ } else
+ state = END_LINE;
+ break;
+ case BEGIN_HEX:
+ if (c == 'x' || c == 'X') {
+ state = NUM_VALUE;
+ base = 16;
+ numValue = 0;
+ i = 0;
+ break;
+ } else if (isDigit(c, 10)) {
+ state = NUM_VALUE;
+ base = 10;
+ numValue = getDigitValue(c, base);
+ break;
+ } else if (c != '\n' && c != '\r') {
+ state = END_LINE;
+ break;
+ }
+ // fall through to numValue to handle numValue
+ [[fallthrough]];
+
+ case NUM_VALUE:
+ if (isDigit(c, base)) {
+ numValue *= base;
+ numValue += getDigitValue(c, base);
+ ++i;
+ } else if (bflag == 1 &&
+ (c == ' ' || c == '\r' || c == '\n' || c == '\t')) {
+ break;
+ } else if (base == 16 &&
+ (c == ',' || c == ':' || c == '-' || c == ' ' || c == '}')) {
+ if (c == '}') {
+ bflag = 0;
+ }
+ if (i > 0) {
+ int n = (i + 1) / 2;
+ while (n-- > 0) {
+ numValue = numValue >> (n * 8);
+ unsigned char c = (numValue)&0xFF;
+ strValue.push_back(c);
+ }
+ }
+
+ Set(IsStringValue);
+ numValue = 0;
+ i = 0;
+ } else {
+ if (c == '\n' || c == '\r') {
+ if (bflag == 0) {
+ state = BEGIN_LINE;
+ }
+ } else {
+ if (bflag == 0) {
+ state = END_LINE;
+ }
+ }
+ if (Is(IsStringValue) && base == 16 && i > 0) {
+ int n = (i + 1) / 2;
+ while (n-- > 0) strValue.push_back(((numValue >> (n * 8)) & 0xFF));
+ }
+ if (strValue.length() > 0)
+ pParam = new CNfcParam(token.c_str(), strValue);
+ else
+ pParam = new CNfcParam(token.c_str(), numValue);
+ add(pParam);
+ strValue.erase();
+ numValue = 0;
+ }
+ break;
+ case STR_VALUE:
+ if (c == '"') {
+ strValue.push_back('\0');
+ state = END_LINE;
+ pParam = new CNfcParam(token.c_str(), strValue);
+ add(pParam);
+ } else if (isPrintable(c))
+ strValue.push_back(c);
+ break;
+ case END_LINE:
+ if (c == '\n' || c == '\r') state = BEGIN_LINE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ delete[] p_config;
+
+ moveFromList();
+ return size() > 0;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::CNfcConfig()
+**
+** Description: class constructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcConfig::CNfcConfig() : mValidFile(true), state(0) {}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::~CNfcConfig()
+**
+** Description: class destructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcConfig::~CNfcConfig() {}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::GetInstance()
+**
+** Description: get class singleton object
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcConfig& CNfcConfig::GetInstance() {
+ static CNfcConfig theInstance;
+ if (theInstance.size() == 0 && theInstance.mValidFile) {
+ string strPath;
+ if (alternative_config_path[0] != '\0') {
+ strPath.assign(alternative_config_path);
+ strPath += config_name;
+ theInstance.readConfig(strPath.c_str(), true);
+ if (!theInstance.empty()) {
+ return theInstance;
+ }
+ }
+ findConfigFilePathFromTransportConfigPaths(config_name, strPath);
+ theInstance.readConfig(strPath.c_str(), true);
+ }
+
+ return theInstance;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::getValue()
+**
+** Description: get a string value of a setting
+**
+** Returns: true if setting exists
+** false if setting does not exist
+**
+*******************************************************************************/
+bool CNfcConfig::getValue(const char* name, char* pValue, size_t len) const {
+ const CNfcParam* pParam = find(name);
+ if (pParam == NULL) return false;
+
+ if (pParam->str_len() > 0) {
+ memset(pValue, 0, len);
+ memcpy(pValue, pParam->str_value(), pParam->str_len());
+ return true;
+ }
+ return false;
+}
+
+bool CNfcConfig::getValue(const char* name, char* pValue, long len,
+ long* readlen) const {
+ const CNfcParam* pParam = find(name);
+ if (pParam == NULL) return false;
+
+ if (pParam->str_len() > 0) {
+ if (pParam->str_len() <= (unsigned long)len) {
+ memset(pValue, 0, len);
+ memcpy(pValue, pParam->str_value(), pParam->str_len());
+ *readlen = pParam->str_len();
+ } else {
+ *readlen = -1;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::getValue()
+**
+** Description: get a long numerical value of a setting
+**
+** Returns: true if setting exists
+** false if setting does not exist
+**
+*******************************************************************************/
+bool CNfcConfig::getValue(const char* name, unsigned long& rValue) const {
+ const CNfcParam* pParam = find(name);
+ if (pParam == NULL) return false;
+
+ if (pParam->str_len() == 0) {
+ rValue = static_cast<unsigned long>(pParam->numValue());
+ return true;
+ }
+ return false;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::getValue()
+**
+** Description: get a short numerical value of a setting
+**
+** Returns: true if setting exists
+** false if setting does not exist
+**
+*******************************************************************************/
+bool CNfcConfig::getValue(const char* name, unsigned short& rValue) const {
+ const CNfcParam* pParam = find(name);
+ if (pParam == NULL) return false;
+
+ if (pParam->str_len() == 0) {
+ rValue = static_cast<unsigned short>(pParam->numValue());
+ return true;
+ }
+ return false;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::find()
+**
+** Description: search if a setting exist in the setting array
+**
+** Returns: pointer to the setting object
+**
+*******************************************************************************/
+#if (NFC_SEC_NOT_OPEN_INCLUDED == TRUE)
+const CNfcParam* CNfcConfig::find(const char* p_name) const {
+ if (size() == 0) return NULL;
+
+ std::string firstField;
+
+ if (UserPrefix.size() > 0) {
+ // Find first priority field
+ firstField.erase();
+ firstField += "+";
+ firstField += UserPrefix;
+ firstField += "_";
+ firstField += p_name;
+
+ const CNfcParam* ret = _find(firstField.c_str());
+ if (ret != NULL) return ret;
+ }
+
+ return _find(p_name);
+}
+
+const CNfcParam* CNfcConfig::_find(const char* p_name) const {
+ for (const_iterator it = begin(), itEnd = end(); it != itEnd; ++it) {
+ if (**it < p_name)
+ continue;
+ else if (**it == p_name) {
+ if ((*it)->str_len() > 0)
+ ALOGD("%s found %s=%s\n", __func__, p_name, (*it)->str_value());
+ else
+ ALOGD("%s found %s=(0x%lX)\n", __func__, p_name, (*it)->numValue());
+ return *it;
+ } else
+ break;
+ }
+
+ return NULL;
+}
+#else
+const CNfcParam* CNfcConfig::find(const char* p_name) const {
+ if (size() == 0) return NULL;
+
+ for (const_iterator it = begin(), itEnd = end(); it != itEnd; ++it) {
+ if (**it < p_name) {
+ continue;
+ } else if (**it == p_name) {
+ if ((*it)->str_len() > 0) {
+ ALOGD("%s found %s=%s\n", __func__, p_name, (*it)->str_value());
+
+ } else {
+ ALOGD("%s found %s=(0x%lx)\n", __func__, p_name, (*it)->numValue());
+ }
+ return *it;
+ } else
+ break;
+ }
+ return NULL;
+}
+#endif
+/*******************************************************************************
+**
+** Function: CNfcConfig::clean()
+**
+** Description: reset the setting array
+**
+** Returns: none
+**
+*******************************************************************************/
+void CNfcConfig::clean() {
+ if (size() == 0) return;
+
+ for (iterator it = begin(), itEnd = end(); it != itEnd; ++it) delete *it;
+ clear();
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::Add()
+**
+** Description: add a setting object to the list
+**
+** Returns: none
+**
+*******************************************************************************/
+void CNfcConfig::add(const CNfcParam* pParam) {
+ if (m_list.size() == 0) {
+ m_list.push_back(pParam);
+ return;
+ }
+ for (list<const CNfcParam*>::iterator it = m_list.begin(),
+ itEnd = m_list.end();
+ it != itEnd; ++it) {
+ if (**it < pParam->c_str()) continue;
+ m_list.insert(it, pParam);
+ return;
+ }
+ m_list.push_back(pParam);
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::moveFromList()
+**
+** Description: move the setting object from list to array
+**
+** Returns: none
+**
+*******************************************************************************/
+void CNfcConfig::moveFromList() {
+ if (m_list.size() == 0) return;
+
+ for (list<const CNfcParam*>::iterator it = m_list.begin(),
+ itEnd = m_list.end();
+ it != itEnd; ++it)
+ push_back(*it);
+ m_list.clear();
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::moveToList()
+**
+** Description: move the setting object from array to list
+**
+** Returns: none
+**
+*******************************************************************************/
+void CNfcConfig::moveToList() {
+ if (m_list.size() != 0) m_list.clear();
+
+ for (iterator it = begin(), itEnd = end(); it != itEnd; ++it)
+ m_list.push_back(*it);
+ clear();
+}
+/*******************************************************************************
+**
+** Function: CNfcParam::CNfcParam()
+**
+** Description: class constructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcParam::CNfcParam() : m_numValue(0) {}
+
+/*******************************************************************************
+**
+** Function: CNfcParam::~CNfcParam()
+**
+** Description: class destructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcParam::~CNfcParam() {}
+
+/*******************************************************************************
+**
+** Function: CNfcParam::CNfcParam()
+**
+** Description: class copy constructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcParam::CNfcParam(const char* name, const string& value)
+ : string(name), m_str_value(value), m_numValue(0) {}
+
+/*******************************************************************************
+**
+** Function: CNfcParam::CNfcParam()
+**
+** Description: class copy constructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcParam::CNfcParam(const char* name, unsigned long value)
+ : string(name), m_numValue(value) {}
+
+/*******************************************************************************
+**
+** Function: GetStrValue
+**
+** Description: API function for getting a string value of a setting
+**
+** Returns: True if found, otherwise False.
+**
+*/
+extern "C" int GetStrValue(const char* name, char* pValue, // SLSI
+ unsigned long len) {
+ CNfcConfig& rConfig = CNfcConfig::GetInstance();
+
+ return rConfig.getValue(name, pValue, len);
+}
+/*******************************************************************************
+**
+** Function: GetByteArrayValue()
+**
+** Description: Read byte array value from the config file.
+**
+** Parameters:
+** name - name of the config param to read.
+** pValue - pointer to input buffer.
+** bufflen - input buffer length.
+** len - out parameter to return the number of bytes read from
+** config file, return -1 in case bufflen is not enough.
+**
+** Returns: TRUE[1] if config param name is found in the config file, else
+** FALSE[0]
+**
+*******************************************************************************/
+extern "C" int GetByteArrayValue(const char* name, char* pValue, // SLSI
+ long bufflen, long* len) {
+ CNfcConfig& rConfig = CNfcConfig::GetInstance();
+
+ return rConfig.getValue(name, pValue, bufflen, len);
+}
+/*******************************************************************************
+**
+** Function: GetNumValue
+**
+** Description: API function for getting a numerical value of a setting
+**
+** Returns: true, if successful
+**
+*******************************************************************************/
+extern "C" int GetNumValue(const char* name, void* pValue, // SLSI
+ unsigned long len) {
+ if (!pValue) return false;
+
+ CNfcConfig& rConfig = CNfcConfig::GetInstance();
+ const CNfcParam* pParam = rConfig.find(name);
+
+ if (pParam == NULL) return false;
+ unsigned long v = pParam->numValue();
+ if (v == 0 && pParam->str_len() > 0 && pParam->str_len() < 4) {
+ const unsigned char* p = (const unsigned char*)pParam->str_value();
+ for (unsigned int i = 0; i < pParam->str_len(); ++i) {
+ v *= 256;
+ v += *p++;
+ }
+ }
+ switch (len) {
+ case sizeof(unsigned long):
+ *(static_cast<unsigned long*>(pValue)) = (unsigned long)v;
+ break;
+ case sizeof(unsigned short):
+ *(static_cast<unsigned short*>(pValue)) = (unsigned short)v;
+ break;
+ case sizeof(unsigned char):
+ *(static_cast<unsigned char*>(pValue)) = (unsigned char)v;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
diff --git a/halimpl/src/device.cc b/halimpl/src/device.cc
new file mode 100644
index 0000000..64c128f
--- /dev/null
+++ b/halimpl/src/device.cc
@@ -0,0 +1,346 @@
+/*
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <pthread.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "device.h"
+#include "hal.h"
+#include "osi.h"
+#include "sec_nfc.h"
+#include "util.h"
+
+int pw_driver, tr_driver;
+pthread_mutex_t tr_lock;
+int tr_closer;
+bool isSleep;
+int wakeup_delay;
+bool log_ptr;
+eNFC_DEV_MODE dev_state;
+tOSI_TASK_HANDLER read_task;
+
+// [Start] Workaround - i2c write fail(self wakeup)
+bool first_wakeup;
+// [End] Workaround - i2c write fail(self wakeup)
+void read_thread(void);
+void data_trace(const char* head, int len, uint8_t* p_data);
+
+int device_init(int data_trace) {
+ dev_state = NFC_DEV_MODE_OFF;
+ log_ptr = data_trace;
+
+ read_task = OSI_task_allocate("read_task", read_thread);
+ if (!read_task) {
+ OSI_loge("Failed to allocate task for read thread!!");
+ return -1;
+ }
+
+ pthread_mutex_init(&tr_lock, NULL);
+
+ return 0;
+}
+
+void device_deinit() {
+ device_close();
+ pthread_mutex_destroy(&tr_lock);
+ OSI_task_free(read_task);
+}
+
+int device_open() {
+ int ret;
+ char pw_driver_name[64];
+ char tr_driver_name[64];
+
+ ret = get_config_string(cfg_name_table[CFG_POWER_DRIVER], pw_driver_name,
+ sizeof(pw_driver_name));
+ if (ret == 0) return -EPERM;
+
+ ret = get_config_string(cfg_name_table[CFG_TRANS_DRIVER], tr_driver_name,
+ sizeof(tr_driver_name));
+ if (ret == 0) return -EPERM;
+
+ pw_driver = open(pw_driver_name, O_RDWR | O_NOCTTY);
+ if (pw_driver < 0) {
+ OSI_loge("Failed to open device driver: %s, pw_driver : 0x%x, errno = %d",
+ pw_driver_name, pw_driver, errno);
+ return pw_driver;
+ }
+
+ tr_driver = pw_driver;
+
+ OSI_loge("pw_driver: %d, tr_driver: %d", pw_driver, tr_driver);
+ device_set_mode(NFC_DEV_MODE_BOOTLOADER);
+
+ if (OSI_OK != OSI_task_run(read_task)) {
+ OSI_loge("Failed to run read task!!");
+ OSI_task_stop(read_task);
+ close(tr_driver);
+ close(pw_driver);
+ return -1;
+ }
+
+ if (!get_config_int(cfg_name_table[CFG_WAKEUP_DELAY], &wakeup_delay))
+ wakeup_delay = 10;
+
+ return 0;
+}
+
+void device_close(void) {
+ close(tr_driver);
+ close(pw_driver);
+
+ pthread_mutex_lock(&tr_lock);
+ tr_driver = -1;
+ pw_driver = -1;
+ pthread_mutex_unlock(&tr_lock);
+
+ if (tr_closer != 0) write(tr_closer, "x", 1);
+
+ OSI_task_stop(read_task);
+}
+
+int device_set_mode(eNFC_DEV_MODE mode) {
+ int ret;
+
+ OSI_logt("device mode chage: %d -> %d", dev_state, mode);
+ ret = ioctl(pw_driver, SEC_NFC_SET_MODE, (int)mode);
+ if (!ret) {
+ if (mode == NFC_DEV_MODE_ON) isSleep = true;
+ dev_state = mode;
+ }
+
+ return ret;
+}
+
+int device_sleep(void) {
+ if (isSleep) return 0;
+
+ isSleep = true;
+ OSI_logt("NFC can be going to sleep");
+ return ioctl(pw_driver, SEC_NFC_SLEEP, 0);
+}
+
+int device_wakeup(void) {
+ int ret = 0;
+ if (!isSleep) return 0;
+
+ isSleep = false;
+ // [Start] Workaround - i2c write fail(self wakeup)
+ first_wakeup = true;
+ // [End] Workaround - i2c write fail(self wakeup)
+ ret = ioctl(pw_driver, SEC_NFC_WAKEUP, 0);
+
+ /* START [H16031401] */
+ if (nfc_hal_info.state == HAL_STATE_SERVICE &&
+ nfc_hal_info.msg_event == HAL_EVT_READ)
+ return ret;
+ /* END [H16031401] */
+ OSI_logt("Wakeup! in %d ms", wakeup_delay);
+ /* wakeup delay */
+ OSI_delay(wakeup_delay);
+ OSI_logt("exit");
+
+ return ret;
+}
+
+int device_write(uint8_t* data, size_t len) {
+ OSI_logt("enter");
+ int ret = 0;
+ int total = 0;
+ int retry = 1;
+
+ while (len != 0) {
+ OSI_logt("before system call");
+ ret = write(tr_driver, data + total, len);
+ OSI_logt("after system call");
+ if (ret < 0) {
+ OSI_loge("write error ret = %d, errno = %d, retry = %d", ret, errno,
+ retry);
+ if (retry++ < 3 && (nfc_hal_info.flag & HAL_FLAG_RETRY_TRNS)) {
+ // [Start] Workaround - i2c write fail(self wakeup)
+ if ((retry == 2) && (first_wakeup == true)) {
+ ret = ioctl(pw_driver, SEC_NFC_SLEEP, 0);
+ OSI_delay(1);
+ ret = ioctl(pw_driver, SEC_NFC_WAKEUP, 0);
+
+ OSI_delay(wakeup_delay);
+ first_wakeup = false;
+ continue;
+ }
+ // [End] Workaround - i2c write fail(self wakeup)
+ else {
+ OSI_delay(5);
+ continue;
+ }
+ }
+ break;
+ }
+ total += ret;
+ len -= ret;
+ }
+
+ if (len == 0) data_trace("Send", total, data);
+
+ OSI_logt("exit");
+ return total;
+}
+
+int device_read(uint8_t* buffer, size_t len) {
+ int ret = 0;
+ int total = 0;
+ int retry = 1;
+
+ while (len != 0) {
+ ret = read(tr_driver, buffer + total, len);
+ if (ret <= 0) {
+ OSI_loge("Read error ret = %d, errno = %d", ret, errno);
+ if (retry++ < 3 && (nfc_hal_info.flag & HAL_FLAG_RETRY_TRNS)) continue;
+ break;
+ }
+
+ total += ret;
+ len -= ret;
+ }
+
+ return total;
+}
+
+void read_thread(void) {
+ tOSI_QUEUE_HANDLER msg_que = NULL;
+ tNFC_HAL_MSG* msg = NULL;
+ fd_set rfds;
+ uint8_t header[NCI_HDR_SIZE];
+ int close_pipe[2];
+ int max_fd;
+ struct timeval tv;
+ struct timeval* ptv = NULL;
+ int ret;
+
+ OSI_logt("enter");
+ /* get msg que */
+ msg_que = OSI_queue_get_handler("msg_q");
+ if (!msg_que) {
+ OSI_loge("Not find %s queue!! exit read thread", "msg_q");
+ return;
+ }
+
+ /* closer */
+ if (pipe(close_pipe) < 0) {
+ OSI_loge("pipe open error for closing read thread");
+ close_pipe[0] = 0;
+ close_pipe[1] = 0;
+ ptv = &tv;
+ }
+ tr_closer = close_pipe[1];
+ max_fd = (close_pipe[0] > tr_driver) ? close_pipe[0] : tr_driver;
+
+ while (OSI_task_isRun(read_task) == OSI_RUN) {
+ pthread_mutex_lock(&tr_lock);
+ if (tr_driver < 0) {
+ pthread_mutex_unlock(&tr_lock);
+ break;
+ }
+ FD_ZERO(&rfds);
+ FD_SET(tr_driver, &rfds);
+ pthread_mutex_unlock(&tr_lock);
+
+ if (close_pipe[0] > 0) {
+ FD_SET(close_pipe[0], &rfds);
+ } else {
+ tv.tv_sec = 0;
+ tv.tv_usec = 2000;
+ }
+
+ ret = select(max_fd + 1, &rfds, NULL, NULL, ptv);
+
+ pthread_mutex_lock(&tr_lock);
+ if (tr_driver < 0) {
+ pthread_mutex_unlock(&tr_lock);
+ break;
+ }
+ pthread_mutex_unlock(&tr_lock);
+
+ if (ret == 0) /* timeout */
+ continue;
+ else if (ret < 0 && errno == EINTR) /* signal received */
+ continue;
+ else if (ret < 0) {
+ OSI_loge("Polling error");
+ nfc_stack_cback(HAL_NFC_ERROR_EVT, HAL_NFC_STATUS_OK);
+ break;
+ }
+
+ /* read 3 bytes (header)*/
+ ret = device_read(header, NCI_HDR_SIZE);
+ if (ret == 0)
+ continue;
+ else if (ret != NCI_HDR_SIZE) {
+ OSI_loge("Reading NCI header failed");
+ continue;
+ }
+
+ msg = (tNFC_HAL_MSG*)OSI_mem_get(NCI_CTRL_SIZE);
+ if (!msg) {
+ OSI_loge("Failed to allocate memory!1");
+ nfc_stack_cback(HAL_NFC_ERROR_EVT, HAL_NFC_STATUS_OK);
+ break;
+ }
+
+ /* payload will read upper layer */
+
+ msg->event = HAL_EVT_READ;
+ memcpy((void*)msg->param, (void*)header, NCI_HDR_SIZE);
+
+ ret = OSI_queue_put(msg_que, (void*)msg);
+ OSI_logd("Sent message to HAL message task, remind que: %d", ret);
+ }
+
+ close(close_pipe[0]);
+ close(close_pipe[1]);
+ tr_closer = 0;
+
+ osi_unlock(); // TODO: why?
+
+ OSI_logt("end;");
+}
+
+#define TRACE_BUFFER_SIZE (NCI_CTRL_SIZE * 3 + 1)
+void data_trace(const char* head, int len, uint8_t* p_data) {
+ int i = 0, header;
+ char trace_buffer[TRACE_BUFFER_SIZE + 2];
+
+ header = (dev_state == NFC_DEV_MODE_BOOTLOADER) ? 4 : 3;
+ while (len-- > 0 && i < NCI_CTRL_SIZE) {
+ if (i < header)
+ sprintf(trace_buffer + (i * 3), "%02x ", p_data[i]);
+ else
+ sprintf(trace_buffer + (i * 3 + 2), "%02x ", p_data[i]);
+ i++;
+ }
+
+ if (log_ptr) OSI_logd(" %s(%3d) %s", head, i, trace_buffer);
+}
diff --git a/halimpl/src/hal.cc b/halimpl/src/hal.cc
new file mode 100644
index 0000000..98bdd77
--- /dev/null
+++ b/halimpl/src/hal.cc
@@ -0,0 +1,452 @@
+/*
+ * 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
diff --git a/halimpl/src/hal_nci.cc b/halimpl/src/hal_nci.cc
new file mode 100644
index 0000000..c16b51a
--- /dev/null
+++ b/halimpl/src/hal_nci.cc
@@ -0,0 +1,211 @@
+/*
+ * 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 <hardware/nfc.h>
+#include <string.h>
+
+#include "device.h"
+#include "hal.h"
+#include "hal_msg.h"
+#include "osi.h"
+#include "util.h"
+
+int hal_nci_send(tNFC_NCI_PKT* pkt) {
+ size_t len = (size_t)(pkt->len + NCI_HDR_SIZE);
+ int ret;
+
+ ret = __send_to_device((uint8_t*)pkt, len);
+ if (ret != (int)len
+ /* workaround for retry; F/W I2C issue */
+ && (nfc_hal_info.flag & HAL_FLAG_NTF_TRNS_ERROR)) {
+ OSI_loge("NCI message send failed");
+ OSI_logd("set flag to 0x%06X", nfc_hal_info.flag);
+ } else {
+ util_nci_analyzer(pkt);
+ }
+
+ return ret;
+}
+
+void hal_nci_send_reset(void) {
+ tNFC_NCI_PKT nci_pkt;
+
+ memset(&nci_pkt, 0, sizeof(tNFC_NCI_PKT));
+ nci_pkt.oct0 = NCI_MT_CMD | NCI_PBF_LAST | NCI_GID_CORE;
+ nci_pkt.oid = NCI_CORE_RESET;
+ nci_pkt.len = 0x01;
+ nci_pkt.payload[0] = 0x01; // Reset config
+
+ hal_nci_send(&nci_pkt);
+}
+
+/* START [181106] Patch for supporting NCI v2.0 */
+// [3. CORE_INIT Changes]
+void hal_nci_send_init(int version) {
+ /* END [181106] Patch for supporting NCI v2.0 */
+ tNFC_NCI_PKT nci_pkt;
+
+ /* START [181106] Patch for supporting NCI v2.0 */
+ //[3. CORE_INIT Changes]
+ memset(&nci_pkt, 0, sizeof(tNFC_NCI_PKT));
+ nci_pkt.oct0 = NCI_MT_CMD | NCI_PBF_LAST | NCI_GID_CORE;
+ nci_pkt.oid = NCI_CORE_INIT;
+ nci_pkt.len = 0x00;
+
+ if (version == NCI_VER_2_0) {
+ nci_pkt.len = 0x02;
+ nci_pkt.payload[0] = 0x00;
+ nci_pkt.payload[1] = 0x00;
+ }
+ /* END [181106] Patch for supporting NCI v2.0 */
+
+ hal_nci_send(&nci_pkt);
+}
+
+/* Workaround: Initialization flash of LMRT */
+void hal_nci_send_clearLmrt(void) {
+ tNFC_NCI_PKT nci_pkt;
+
+ memset(&nci_pkt, 0, sizeof(tNFC_NCI_PKT));
+ nci_pkt.oct0 = NCI_MT_CMD | NCI_PBF_LAST | NCI_GID_RF_MANAGE;
+ nci_pkt.oid = 0x01; // RF_SET_LMRT
+ nci_pkt.len = 0x02;
+ nci_pkt.payload[0] = 0x00;
+ nci_pkt.payload[1] = 0x00;
+
+ hal_nci_send(&nci_pkt);
+}
+/* END WA */
+
+void get_clock_info(int rev, int field_name, int* buffer) {
+ char rev_field[50] = {
+ '\0',
+ };
+ int isRevField = 0;
+
+ sprintf(rev_field, "%s_REV%d", cfg_name_table[field_name], rev);
+ isRevField = get_config_count(rev_field);
+ if (rev >= 0 && isRevField) {
+ if (!get_config_int(rev_field, buffer)) *buffer = 0;
+ } else if (!get_config_int(cfg_name_table[field_name], buffer))
+ *buffer = 0;
+}
+
+void hal_nci_send_prop_fw_cfg(void) {
+ tNFC_NCI_PKT nci_pkt;
+ int rev = get_hw_rev();
+
+ memset(&nci_pkt, 0, sizeof(tNFC_NCI_PKT));
+ nci_pkt.oct0 = NCI_MT_CMD | NCI_PBF_LAST | NCI_GID_PROP;
+ nci_pkt.oid = NCI_PROP_FW_CFG;
+
+ nci_pkt.len = 0x01;
+ get_clock_info(rev, CFG_FW_CLK_SPEED, (int*)&nci_pkt.payload[0]);
+ if (nci_pkt.payload[0] == 0xff) {
+ OSI_loge("Set a different value! Current Clock Speed Value : 0x%x",
+ nci_pkt.payload[0]);
+ return;
+ }
+ hal_nci_send(&nci_pkt);
+}
+
+int nci_read_payload(tNFC_HAL_MSG* msg) {
+ tNFC_NCI_PKT* pkt = &msg->nci_packet;
+ int ret;
+
+ ret = device_read(NCI_PAYLOAD(pkt), NCI_LEN(pkt));
+ if (ret != (int)NCI_LEN(pkt)) {
+ OSI_mem_free((tOSI_MEM_HANDLER)msg);
+ OSI_loge("Failed to read payload");
+ return ret;
+ }
+
+ data_trace("Recv", NCI_HDR_SIZE + ret, msg->param);
+ return ret;
+}
+
+void fw_force_update(__attribute__((unused)) void* param) {
+ OSI_loge("need to F/W update!");
+}
+
+void nci_init_timeout(__attribute__((unused)) void* param) {
+ OSI_loge("need to retry!");
+}
+
+bool nfc_hal_prehandler(tNFC_NCI_PKT* pkt) {
+ if (NCI_MT(pkt) == NCI_MT_NTF) {
+ if (NCI_GID(pkt) == NCI_GID_PROP) {
+ /* Again procedure. only for N3 isN3group */
+ if (NCI_OID(pkt) == NCI_PROP_AGAIN) {
+ if (nfc_hal_info.nci_last_pkt) {
+ OSI_logd("NFC requests sending last message again!");
+ hal_update_sleep_timer();
+ device_write((uint8_t*)nfc_hal_info.nci_last_pkt,
+ (size_t)(nfc_hal_info.nci_last_pkt->len + NCI_HDR_SIZE));
+ return false;
+ }
+ }
+ }
+ }
+
+ if (NCI_MT(pkt) == NCI_MT_CMD) {
+ if (NCI_GID(pkt) == NCI_GID_PROP) {
+ if (NCI_OID(pkt) == NCI_PROP_WR_RESET) {
+ hal_nci_send_reset();
+ nfc_hal_info.flag |= HAL_FLAG_PROP_RESET;
+ return false;
+ }
+
+ if (NCI_OID(pkt) == NCI_PROP_SET_SLEEP_TIME) {
+ tNFC_NCI_PKT dummy_rsp;
+ dummy_rsp.oct0 = NCI_MT_RSP | NCI_PBF_LAST | NCI_GID_PROP;
+ dummy_rsp.oid = NCI_OID(pkt);
+ dummy_rsp.len = 1;
+ dummy_rsp.payload[0] = NCI_STATUS_OK;
+
+ if (NCI_LEN(pkt) == 0) {
+ setSleepTimeout(SET_SLEEP_TIME_CFG, 5000);
+ } else {
+ uint32_t timeout = NCI_PAYLOAD(pkt)[0] * 1000; // sec
+ int option = SET_SLEEP_TIME_ONCE;
+
+ if (NCI_LEN(pkt) > 1)
+ timeout += NCI_PAYLOAD(pkt)[1] * 1000 * 60; // min
+
+ if (NCI_LEN(pkt) > 2) option = NCI_PAYLOAD(pkt)[2];
+
+ setSleepTimeout(option, timeout);
+ }
+
+ hal_update_sleep_timer();
+ nfc_data_callback(&dummy_rsp);
+ return false;
+ }
+ }
+ }
+
+ if (NCI_MT(pkt) == NCI_MT_RSP) {
+ if (NCI_GID(pkt) == NCI_GID_CORE) {
+ if (NCI_OID(pkt) == NCI_CORE_RESET) {
+ pkt->oct0 = NCI_MT_RSP | NCI_PBF_LAST | NCI_GID_PROP;
+ pkt->oid = NCI_PROP_WR_RESET;
+ }
+ }
+ }
+ return true;
+}
diff --git a/halimpl/src/hal_task.cc b/halimpl/src/hal_task.cc
new file mode 100644
index 0000000..9528cc0
--- /dev/null
+++ b/halimpl/src/hal_task.cc
@@ -0,0 +1,447 @@
+/*
+ * 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 <hardware/nfc.h>
+#include <malloc.h>
+#include <string.h>
+
+#include "device.h"
+#include "hal.h"
+#include "hal_msg.h"
+#include "osi.h"
+#include "util.h"
+
+#include <cutils/properties.h>
+
+uint32_t fw_update_state = 0;
+/* START [181106] Patch for supporting NCI v2.0 */
+// [1. NCI Version Management]
+int gNciVersion = NCI_VER_1_0; // 0x10 : NCI 1.0, 0x20 : NCI2.0
+/* END [181106] Patch for supporting NCI v2.0 */
+
+static void nfc_hal_state_switch(tNFC_HAL_MSG* msg, eHAL_STATE state) {
+ tNFC_HAL_MSG* new_msg;
+
+ new_msg = (tNFC_HAL_MSG*)OSI_mem_get(HAL_EVT_SIZE);
+ if (!new_msg) {
+ OSI_loge("Failed to memory allocate!");
+ nfc_stack_cback(HAL_NFC_ERROR_EVT, HAL_NFC_STATUS_OK);
+ return;
+ }
+
+ nfc_hal_info.state = state;
+ memcpy(new_msg, msg, sizeof(HAL_EVT_SIZE));
+ OSI_queue_put(nfc_hal_info.msg_q, (void*)new_msg);
+}
+
+void hal_sleep(__attribute__((unused)) void* param) {
+ nfc_hal_info.flag &= ~HAL_FLAG_PROP_ONE_TIMER;
+ nfc_hal_info.cfg.override_timeout = 0;
+ device_sleep();
+}
+
+void hal_update_sleep_timer(void) {
+ device_wakeup();
+
+ /* workaround for double timer */
+ if (nfc_hal_info.flag & HAL_FLAG_MASK_USING_TIMER) return;
+
+ if (nfc_hal_info.flag & HAL_FLAG_PROP_ONE_TIMER)
+ OSI_timer_start(nfc_hal_info.sleep_timer, nfc_hal_info.cfg.override_timeout,
+ (tOSI_TIMER_CALLBACK)hal_sleep, NULL);
+ else
+ OSI_timer_start(nfc_hal_info.sleep_timer, nfc_hal_info.cfg.sleep_timeout,
+ (tOSI_TIMER_CALLBACK)hal_sleep, NULL);
+}
+
+int __send_to_device(uint8_t* data, size_t len) {
+ hal_update_sleep_timer();
+ if (nfc_hal_info.nci_last_pkt)
+ memcpy((void*)nfc_hal_info.nci_last_pkt, (void*)data, len);
+
+ return device_write(data, len);
+}
+
+void nfc_hal_open_sm(tNFC_HAL_MSG* msg) {
+ tNFC_NCI_PKT* pkt = &msg->nci_packet;
+
+ switch (msg->event) {
+ case HAL_EVT_OPEN:
+ device_set_mode(NFC_DEV_MODE_ON);
+ hal_nci_send_prop_fw_cfg();
+ break;
+ case HAL_EVT_READ:
+ nci_read_payload(msg);
+ util_nci_analyzer(pkt);
+ if (NCI_MT(pkt) != NCI_MT_RSP || NCI_GID(pkt) != NCI_GID_PROP ||
+ NCI_OID(pkt) != NCI_PROP_FW_CFG) {
+ OSI_logd("Not matched rsponse!! we expect NCI_PROP_FW_CFG_RSP");
+ } else {
+ if (NCI_STATUS(pkt) != NCI_STATUS_OK &&
+ NCI_STATUS(pkt) != NCI_STATUS_E_SYNTAX &&
+ NCI_STATUS(pkt) != NCI_CLOCK_STATUS_SYNTAX_ERROR &&
+ NCI_STATUS(pkt) != NCI_CLOCK_STATUS_MISMATCHED &&
+ NCI_STATUS(pkt) != NCI_CLOCK_STATUS_FULL) {
+ OSI_loge("Failed to config FW, status: %d", NCI_STATUS(pkt));
+ break;
+ } else {
+ if (NCI_STATUS(pkt) == NCI_STATUS_OK) {
+ nfc_hal_info.state = HAL_STATE_POSTINIT;
+ nfc_stack_cback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_OK);
+ break;
+ }
+ OSI_loge("Failed to config FW, status: %d", NCI_STATUS(pkt));
+ }
+ }
+ break;
+ case HAL_EVT_COMPLETE_FAILED:
+ device_set_mode(NFC_DEV_MODE_OFF);
+ nfc_stack_cback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_FAILED);
+ break;
+
+ case HAL_EVT_TERMINATE:
+ // TODO: terminate
+ break;
+ default:
+ break;
+ }
+}
+
+void nfc_hal_postinit_sm(tNFC_HAL_MSG* msg) {
+ tNFC_NCI_PKT* pkt = &msg->nci_packet;
+
+ switch (msg->event) {
+ case HAL_EVT_CORE_INIT:
+ nfc_hal_info.vs_info.state = VS_INIT;
+ nfc_hal_state_switch(msg, HAL_STATE_VS);
+ break;
+
+ case HAL_EVT_WRITE:
+ if (NCI_GID(pkt) == NCI_GID_CORE) {
+ if (NCI_OID(pkt) == NCI_CORE_RESET && NCI_LEN(pkt) == 1) {
+ if (nfc_hal_info.flag & HAL_FLAG_ALREADY_RESET) goto complete;
+
+ nfc_hal_info.flag |= HAL_FLAG_W4_CORE_RESET_RSP;
+ OSI_timer_start(nfc_hal_info.nci_timer, 1000,
+ (tOSI_TIMER_CALLBACK)fw_force_update, NULL);
+ OSI_logd("set flag to 0x%06X", nfc_hal_info.flag);
+ } else if (NCI_OID(pkt) == NCI_CORE_INIT &&
+ (NCI_LEN(pkt) == 0 || NCI_LEN(pkt) == 2)) {
+ if (nfc_hal_info.flag & HAL_FLAG_ALREADY_INIT) goto complete;
+
+ nfc_hal_info.flag |= HAL_FLAG_W4_CORE_INIT_RSP;
+ OSI_timer_start(nfc_hal_info.nci_timer, 1000,
+ (tOSI_TIMER_CALLBACK)nci_init_timeout, NULL);
+ OSI_logd("set flag to 0x%06X", nfc_hal_info.flag);
+ }
+ }
+ hal_nci_send(&msg->nci_packet);
+ break;
+
+ case HAL_EVT_READ:
+ nci_read_payload(msg);
+ if (NCI_GID(pkt) == NCI_GID_CORE) {
+ if (NCI_OID(pkt) == NCI_CORE_RESET) {
+ OSI_logd("Respond CORE_RESET_RSP");
+ nfc_hal_info.flag &= ~HAL_FLAG_W4_CORE_RESET_RSP;
+ nfc_hal_info.flag |= HAL_FLAG_ALREADY_RESET;
+ /* START [19082300] Patch for supporting NCI v2.0 */
+ // [1. NCI Version Management]
+ // gNciVersion : 0x10 : NCI1.0, 0x20 : NCI2.0
+ if ((NCI_LEN(pkt) == 0x03) && NCI_MT(pkt) == NCI_MT_RSP)
+ gNciVersion = NCI_VER_1_0;
+ else {
+ gNciVersion = NCI_VER_2_0;
+ }
+ /* END [19082300] Patch for supporting NCI v2.0 */
+ } else if (NCI_OID(pkt) == NCI_CORE_INIT) {
+ OSI_logd("Respond CORE_INIT_RSP");
+ nfc_hal_info.flag &= ~HAL_FLAG_W4_CORE_INIT_RSP;
+ nfc_hal_info.flag |= HAL_FLAG_ALREADY_INIT;
+ }
+ OSI_timer_stop(nfc_hal_info.nci_timer);
+ }
+ util_nci_analyzer(pkt);
+ nfc_data_callback(&msg->nci_packet);
+ break;
+
+ case HAL_EVT_COMPLETE:
+ complete:
+ nfc_hal_info.flag |= HAL_FLAG_NTF_TRNS_ERROR | HAL_FLAG_RETRY_TRNS;
+ nfc_hal_info.state = HAL_STATE_SERVICE;
+
+ OSI_logd("Complete postinit sm");
+
+ nfc_stack_cback(HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_OK);
+ break;
+ case HAL_EVT_COMPLETE_FAILED:
+ nfc_stack_cback(HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_FAILED);
+ break;
+
+ /* START - VTS */
+ case HAL_EVT_POWER_CYCLE:
+ OSI_logt("HAL_EVT_POWER_CYCLE");
+ device_sleep();
+ device_close();
+ OSI_logt("HAL state change to POWERCYCLE");
+ nfc_hal_state_switch(msg, HAL_STATE_POWERCYCLE);
+ break;
+ /* END - VTS */
+
+ case HAL_EVT_TERMINATE:
+ // TODO: terminate
+ break;
+ default:
+ break;
+ }
+}
+
+void nfc_hal_vs_sm(tNFC_HAL_MSG* msg) {
+ tNFC_HAL_VS_INFO* vs = &nfc_hal_info.vs_info;
+
+ if (msg->event != HAL_EVT_READ && msg->event != HAL_EVT_CORE_INIT) {
+ OSI_loge("Unexpected event [%d]", msg->event);
+ return;
+ }
+
+ if (vs->state != VS_INIT) {
+ nci_read_payload(msg);
+ util_nci_analyzer(pkt);
+ }
+
+ switch (vs->state) {
+ case VS_INIT:
+ hal_nci_send_clearLmrt();
+ vs->state = VS_W4_COMPLETE;
+ break;
+ case VS_W4_COMPLETE:
+ OSI_logd("Vendor Specific is complete.");
+ msg->event = HAL_EVT_COMPLETE;
+ nfc_hal_state_switch(msg, HAL_STATE_POSTINIT);
+ break;
+ default:
+ OSI_loge("Unexpected event [%d]", msg->event);
+ break;
+ }
+}
+
+void nfc_hal_service_sm(tNFC_HAL_MSG* msg) {
+ tNFC_NCI_PKT* pkt = &msg->nci_packet;
+ /* START [H16031401] */
+ nfc_hal_info.msg_event = msg->event;
+ /* END [H16031401] */
+
+ switch (msg->event) {
+ /* START - VTS */
+ case HAL_EVT_CORE_INIT:
+ nfc_hal_info.vs_info.state = VS_INIT;
+ nfc_hal_state_switch(msg, HAL_STATE_VS);
+ break;
+ /* END - VTS */
+ case HAL_EVT_WRITE:
+ if (nfc_hal_prehandler(pkt)) hal_nci_send(pkt);
+ break;
+ case HAL_EVT_READ:
+ nci_read_payload(msg);
+ util_nci_analyzer(pkt);
+ hal_update_sleep_timer();
+ if (nfc_hal_prehandler(pkt)) nfc_data_callback(pkt);
+ break;
+ case HAL_EVT_CONTROL_GRANTED:
+ nfc_hal_state_switch(msg, HAL_STATE_GRANTED);
+ break;
+ case HAL_EVT_TERMINATE:
+ // TODO: terminate
+ break;
+ default:
+ break;
+ }
+}
+
+static void nfc_hal_grant_finish(void) {
+ nfc_stack_cback(HAL_NFC_RELEASE_CONTROL_EVT, HAL_NFC_STATUS_OK);
+ nfc_hal_info.state = HAL_STATE_SERVICE;
+ nfc_hal_info.grant_cback = NULL;
+}
+
+void nfc_hal_grant_sm(tNFC_HAL_MSG* msg) {
+ tNFC_NCI_PKT* pkt = &msg->nci_packet;
+ uint8_t cback_ret = HAL_GRANT_FINISH;
+
+ /* Granted mode is not need to SLEEP.
+ * hal should pend granted mode just few time */
+ switch (msg->event) {
+ case HAL_EVT_READ:
+ nci_read_payload(msg);
+ util_nci_analyzer(pkt);
+ cback_ret = nfc_hal_info.grant_cback(pkt);
+ if (cback_ret == HAL_GRANT_FINISH) nfc_hal_grant_finish();
+
+ if (cback_ret != HAL_GRANT_SEND_NEXT) break;
+ [[fallthrough]];
+ case HAL_EVT_CONTROL_GRANTED:
+ pkt = (tNFC_NCI_PKT*)OSI_queue_get(nfc_hal_info.nci_q);
+ if (pkt) {
+ // TODO: Should CLF respond?
+ hal_nci_send(pkt);
+ OSI_mem_free((tOSI_MEM_HANDLER)pkt);
+ } else
+ nfc_hal_grant_finish();
+
+ break;
+
+ case HAL_EVT_WRITE:
+ OSI_loge("HAL is in granted mode!");
+ break;
+ }
+}
+/* START - VTS */
+void nfc_hal_power_sm(tNFC_HAL_MSG* msg) {
+ switch (msg->event) {
+ case HAL_EVT_POWER_CYCLE:
+ // have to do is hal open
+ OSI_logt("HAL_EVT_POWER_CYCLE");
+ // nfc_hal_init();
+
+ if (device_open()) return;
+
+ msg->event = HAL_EVT_OPEN;
+ nfc_hal_state_switch(msg, HAL_STATE_OPEN);
+ break;
+ default:
+ break;
+ }
+}
+/* END - VTS */
+
+/* TASK */
+void nfc_hal_task(void) {
+ tNFC_HAL_MSG* msg;
+ eHAL_STATE old_st;
+
+ OSI_logt("enter!");
+
+ if (!nfc_hal_info.msg_task || !nfc_hal_info.nci_timer ||
+ !nfc_hal_info.msg_q || !nfc_hal_info.nci_q) {
+ OSI_loge("msg_task = %p, nci_timer = %p, msg_q = %p, nci_q = %p",
+ nfc_hal_info.msg_task, nfc_hal_info.nci_timer, nfc_hal_info.msg_q,
+ nfc_hal_info.nci_q);
+
+ nfc_hal_deinit();
+ OSI_loge("nfc_hal initialization is not succeeded.");
+ nfc_stack_cback(HAL_NFC_ERROR_EVT, HAL_NFC_STATUS_FAILED);
+ return;
+ }
+
+ while (OSI_task_isRun(nfc_hal_info.msg_task) == OSI_RUN) {
+ msg = (tNFC_HAL_MSG*)OSI_queue_get_wait(nfc_hal_info.msg_q);
+ if (!msg) continue;
+
+ OSI_logd("Got a event: %s(%d)", event_to_string(msg->event), msg->event);
+ if (msg->event == HAL_EVT_TERMINATE) break;
+
+ OSI_logd("current state: %s", state_to_string(nfc_hal_info.state));
+ old_st = nfc_hal_info.state;
+ switch (nfc_hal_info.state) {
+ case HAL_STATE_INIT:
+ case HAL_STATE_DEINIT:
+ case HAL_STATE_OPEN:
+ nfc_hal_open_sm(msg);
+ break;
+ case HAL_STATE_VS:
+ nfc_hal_vs_sm(msg);
+ break;
+ case HAL_STATE_POSTINIT:
+ nfc_hal_postinit_sm(msg);
+ break;
+ case HAL_STATE_SERVICE:
+ nfc_hal_service_sm(msg);
+ break;
+ case HAL_STATE_GRANTED:
+ nfc_hal_grant_sm(msg);
+ break;
+ /* START - VTS */
+ case HAL_STATE_POWERCYCLE:
+ nfc_hal_power_sm(msg);
+ break;
+ /* END - VTS */
+ default:
+ break;
+ }
+ OSI_mem_free((tOSI_MEM_HANDLER)msg);
+
+ if (old_st != nfc_hal_info.state) {
+ OSI_logd("hal state is changed: %s -> %s", state_to_string(old_st),
+ state_to_string(nfc_hal_info.state));
+ }
+ }
+ OSI_logt("exit!");
+}
+
+/* Print */
+const char* event_to_string(uint8_t event) {
+ switch (event) {
+ case HAL_EVT_OPEN:
+ return "HAL_EVT_OPEN";
+ case HAL_EVT_CORE_INIT:
+ return "HAL_EVT_CORE_INIT";
+ case HAL_EVT_WRITE:
+ return "HAL_EVT_WRITE";
+ case HAL_EVT_READ:
+ return "HAL_EVT_READ";
+ case HAL_EVT_CONTROL_GRANTED:
+ return "HAL_EVT_CONTROL_GRANTED";
+ /* START - VTS */
+ case HAL_EVT_POWER_CYCLE:
+ return "HAL_EVT_POWER_CYCLE";
+ /* END - VTS */
+ case HAL_EVT_TERMINATE:
+ return "NFC_HAL_TERMINATE";
+ case HAL_EVT_COMPLETE:
+ return "NFC_HAL_COMPLETE";
+ case HAL_EVT_COMPLETE_FAILED:
+ return "NFC_HAL_COMPLETE_FAILED";
+ }
+ return "Unknown event.";
+}
+
+const char* state_to_string(eHAL_STATE state) {
+ switch (state) {
+ case HAL_STATE_INIT:
+ return "INIT";
+ case HAL_STATE_DEINIT:
+ return "DEINIT";
+ case HAL_STATE_OPEN:
+ return "OPEN";
+ case HAL_STATE_VS:
+ return "VENDOR_SPECIFIC";
+ case HAL_STATE_POSTINIT:
+ return "POST_INIT";
+ case HAL_STATE_SERVICE:
+ return "SERVICE";
+ case HAL_STATE_GRANTED:
+ return "GRANT";
+ /* START - VTS */
+ case HAL_STATE_POWERCYCLE:
+ return "POWER_CYCLE";
+ /* END - VTS */
+ case HAL_STATE_CLOSE:
+ return "CLOSE";
+ }
+ return "Unknown state.";
+}
diff --git a/halimpl/src/util.cc b/halimpl/src/util.cc
new file mode 100644
index 0000000..fa75db0
--- /dev/null
+++ b/halimpl/src/util.cc
@@ -0,0 +1,265 @@
+/*
+ * 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 <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+/* START [H17080801] HAL config file path */
+#define CFG_FILE_1 "/vendor/etc/libnfc-sec-vendor.conf"
+#define CFG_FILE_2 "/etc/libnfc-sec-vendor.conf"
+/* END [H17080801] HAL config file path */
+
+#define isToken(x) (x == ':' || x == '=' || x == ' ' || x == '\t')
+#define skipToken(x) \
+ while (isToken(*x)) x++
+#define skipSpace(x) \
+ while (isspace(*x)) x++
+
+bool willBeContinuous(char* buffer, size_t maxlen) {
+ char* p;
+ size_t len;
+ if (!buffer) return false;
+
+ len = strnlen(buffer, maxlen);
+ if (len == maxlen && buffer[len - 2] != '\n') return true;
+
+ p = buffer + len - 1;
+ while (isspace(*p) && p > buffer) p--;
+ if (*p == '\\') return true;
+ return false;
+}
+
+bool find_by_name_from_current(FILE* file, const char* field) {
+ char *p, buffer[256] = {
+ '\0',
+ };
+ size_t len;
+ int fp;
+ bool skip = false;
+
+ if (!file || !field) return false;
+
+ len = strlen(field);
+ while (!feof(file) && fgets(buffer, sizeof(buffer) - 1, file)) {
+ if (skip) {
+ skip = willBeContinuous(buffer, sizeof(buffer));
+ continue;
+ }
+ skip = willBeContinuous(buffer, sizeof(buffer));
+
+ p = buffer;
+ skipSpace(p);
+ if (*p == '#') continue;
+
+ if (!strncmp((char const*)field, (char const*)p, len)) {
+ fp = -strlen(p);
+ fp += len;
+ return (fseek(file, fp, SEEK_CUR) == 0) ? true : false;
+ }
+ }
+ return false;
+}
+
+bool find_by_name(FILE* file, const char* field) {
+ fseek(file, 0x00, SEEK_SET);
+ return find_by_name_from_current(file, field);
+}
+
+bool __get_config_int(__attribute__((unused)) char* file_path,
+ const char* field, int* data, int option) {
+ FILE* file;
+ char buffer[10], *p, *endp;
+ size_t len;
+ long int val;
+
+ if (!field || !data) return false;
+
+ /* START [H17080801] HAL config file path */
+ if ((file = fopen(CFG_FILE_1, "rb")) == NULL) {
+ OSI_loge("Cannot open config file %s", CFG_FILE_1);
+ if ((file = fopen(CFG_FILE_2, "rb")) == NULL) {
+ OSI_loge("Cannot open config file %s", CFG_FILE_2);
+ return 0;
+ }
+ }
+ /* END [H17080801] HAL config file path */
+
+ if (!find_by_name(file, field)) {
+ OSI_loge("Cannot find the field name [%s]", field);
+ goto fail;
+ }
+
+ if (!fgets(buffer, sizeof(buffer) - 1, file)) {
+ OSI_loge("Read failed");
+ goto fail;
+ }
+
+ if (willBeContinuous(buffer, sizeof(buffer))) // not supported multi line
+ goto fail;
+
+ if ((len = strlen(buffer)) == sizeof(buffer) - 1) {
+ OSI_loge("It is too long data [%s~]; max", buffer);
+ goto fail;
+ }
+
+ p = buffer;
+ skipToken(p);
+ if (*p == '\0') {
+ OSI_loge("It is empty data");
+ goto fail;
+ }
+
+ if (((*p == '0') && (*(p + 1) == 'x')) || option == HAL_UTIL_GET_INT_16)
+ val = strtol(p, &endp, 0x10);
+ else
+ val = strtol(p, &endp, 10);
+
+ if (p == endp) {
+ OSI_loge("Read failed [%s]", buffer);
+ goto fail;
+ }
+
+ OSI_logd("Get config %s: %ld(0x%lx)", field, val, val);
+
+ fclose(file);
+
+ *data = val;
+ return true;
+
+fail:
+ fclose(file);
+ return false;
+}
+
+bool get_config_int(const char* field, int* data) {
+ /* START [17080801] HAL config file path */
+ return __get_config_int((char*)CFG_FILE_1, field, data, 0);
+ /* END [17080801] HAL config file path */
+}
+
+int get_config_string(const char* field, char* strBuffer, size_t bufferSize) {
+ FILE* file;
+ char data[256], *buffer, *p;
+ bool readmore = true;
+ size_t count = 0;
+
+ if (!field || !strBuffer || bufferSize < 1) return 0;
+
+ /* START [H17080801] HAL config file path */
+ if ((file = fopen(CFG_FILE_1, "rb")) == NULL) {
+ OSI_loge("Cannot open config file %s", CFG_FILE_1);
+ if ((file = fopen(CFG_FILE_2, "rb")) == NULL) {
+ OSI_loge("Cannot open config file %s", CFG_FILE_2);
+ return 0;
+ }
+ }
+ /* END [H17080801] HAL config file path */
+
+ if (!find_by_name(file, field)) {
+ OSI_logd("Cannot find the field name [%s]", field);
+ goto fail;
+ }
+
+ if ((buffer = (char*)malloc(bufferSize)) == NULL) {
+ OSI_logd("Cannot allocate temporary buffer for [%s]", field);
+ goto fail;
+ }
+
+ while (count < bufferSize - 1 && readmore) {
+ if (!fgets(data, sizeof(data) - 1, file)) {
+ OSI_loge("Read failed");
+ goto fail_free;
+ }
+
+ readmore = willBeContinuous(data, sizeof(data));
+ p = data;
+ while ((p = strchr(p, '"')) != NULL) // start string
+ {
+ for (p++; *p != '"'; p++) // end string
+ {
+ if (*p == '\n' || *p == '\0' || *p == '\\') {
+ OSI_loge("Cannot find ending point of string");
+ goto fail_free;
+ }
+ buffer[count++] = *p;
+ }
+ p++;
+ }
+ }
+ buffer[count] = '\0';
+
+ OSI_logd("Get config %s: %s", field, buffer);
+ if (count == bufferSize) {
+ if (p == NULL)
+ goto fail_free;
+ else if (*p != '\n')
+ OSI_loge("Overflower!, remained data is [%s]", p);
+ else if (readmore)
+ OSI_loge("Overflower!, data is remained! (multi line)");
+ }
+
+ count++;
+ memcpy(strBuffer, buffer, count);
+ free(buffer);
+
+ fclose(file);
+ return count;
+
+fail_free:
+ free(buffer);
+fail:
+ fclose(file);
+ return 0;
+}
+
+int get_config_count(const char* field) {
+ FILE* file;
+ int count = 0;
+
+ /* START [H17080801] HAL config file path */
+ if ((file = fopen(CFG_FILE_1, "rb")) == NULL) {
+ OSI_loge("Cannot open config file %s", CFG_FILE_1);
+ if ((file = fopen(CFG_FILE_2, "rb")) == NULL) {
+ OSI_loge("Cannot open config file %s", CFG_FILE_2);
+ return 0;
+ }
+ }
+ /* END [H17080801] HAL config file path */
+
+ while (find_by_name_from_current(file, field)) count++;
+
+ fclose(file);
+ return count;
+}
+
+int get_hw_rev() {
+ char* info_file = (char*)"/proc/cpuinfo";
+ char* field = (char*)"Revision";
+ int rev = -1;
+
+ OSI_logd("%s enter;", __func__);
+ __get_config_int(info_file, field, &rev, HAL_UTIL_GET_INT_16);
+ OSI_logd("%s exit; rev = %d", __func__, rev);
+
+ return rev;
+}