Initial Samsung's NFC HAL
authorBongsu Jeon <bongsu.jeon@samsung.com>
Thu, 11 Mar 2021 08:16:21 +0000 (17:16 +0900)
committerBongsu Jeon <bongsu.jeon@samsung.com>
Thu, 11 Mar 2021 10:05:19 +0000 (19:05 +0900)
This is the initial Samsung's AOSP HAL implementation.

Change-Id: I9f2183242ef789c47cf278ac78159855c78ce92c

25 files changed:
1.2/Android.bp [new file with mode: 0644]
1.2/HalSecNfc.h [new file with mode: 0644]
1.2/SecNfc.cpp [new file with mode: 0644]
1.2/SecNfc.h [new file with mode: 0644]
1.2/SecNfcService.cpp [new file with mode: 0644]
1.2/android.hardware.nfc@1.2-service.samsung.rc [new file with mode: 0644]
Android.bp [new file with mode: 0644]
halimpl/include/config.h [new file with mode: 0644]
halimpl/include/device.h [new file with mode: 0644]
halimpl/include/hal.h [new file with mode: 0644]
halimpl/include/hal_msg.h [new file with mode: 0644]
halimpl/include/sec_nfc.h [new file with mode: 0644]
halimpl/include/util.h [new file with mode: 0644]
halimpl/osi/osi.h [new file with mode: 0644]
halimpl/osi/osi_common.h [new file with mode: 0644]
halimpl/osi/osi_main.cc [new file with mode: 0644]
halimpl/osi/osi_memory.cc [new file with mode: 0644]
halimpl/osi/osi_task.cc [new file with mode: 0644]
halimpl/osi/osi_timer.cc [new file with mode: 0644]
halimpl/src/config.cpp [new file with mode: 0644]
halimpl/src/device.cc [new file with mode: 0644]
halimpl/src/hal.cc [new file with mode: 0644]
halimpl/src/hal_nci.cc [new file with mode: 0644]
halimpl/src/hal_task.cc [new file with mode: 0644]
halimpl/src/util.cc [new file with mode: 0644]

diff --git a/1.2/Android.bp b/1.2/Android.bp
new file mode 100644 (file)
index 0000000..fbd21fe
--- /dev/null
@@ -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 (file)
index 0000000..33a9146
--- /dev/null
@@ -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 (file)
index 0000000..6eceaa5
--- /dev/null
@@ -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 (file)
index 0000000..51bbd69
--- /dev/null
@@ -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 (file)
index 0000000..fb11228
--- /dev/null
@@ -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 (file)
index 0000000..c026cde
--- /dev/null
@@ -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 (file)
index 0000000..4bcd3b8
--- /dev/null
@@ -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 (file)
index 0000000..cafc4a4
--- /dev/null
@@ -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 (file)
index 0000000..99ec3b6
--- /dev/null
@@ -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 (file)
index 0000000..153cd99
--- /dev/null
@@ -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 (file)
index 0000000..a886053
--- /dev/null
@@ -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 (file)
index 0000000..8826bed
--- /dev/null
@@ -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 (file)
index 0000000..5af4a29
--- /dev/null
@@ -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 (file)
index 0000000..ac29c54
--- /dev/null
@@ -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 (file)
index 0000000..582c669
--- /dev/null
@@ -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 (file)
index 0000000..9b67265
--- /dev/null
@@ -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 (file)
index 0000000..434afd7
--- /dev/null
@@ -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 (file)
index 0000000..9174b0e
--- /dev/null
@@ -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 (file)
index 0000000..6d65cab
--- /dev/null
@@ -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 (file)
index 0000000..f488ed2
--- /dev/null
@@ -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 (file)
index 0000000..64c128f
--- /dev/null
@@ -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 (file)
index 0000000..98bdd77
--- /dev/null
@@ -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 (file)
index 0000000..c16b51a
--- /dev/null
@@ -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 (file)
index 0000000..9528cc0
--- /dev/null
@@ -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 (file)
index 0000000..fa75db0
--- /dev/null
@@ -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;
+}