1/* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16#include "HciEventManager.h" 17#include <android-base/stringprintf.h> 18#include <base/logging.h> 19#include <nativehelper/ScopedLocalRef.h> 20#include "JavaClassConstants.h" 21#include "NfcJniUtil.h" 22#include "nfc_config.h" 23 24extern bool nfc_debug_enabled; 25const char* APP_NAME = "NfcNci"; 26uint8_t HciEventManager::sEsePipe; 27uint8_t HciEventManager::sSimPipe; 28 29using android::base::StringPrintf; 30 31HciEventManager::HciEventManager() : mNativeData(nullptr) {} 32 33HciEventManager& HciEventManager::getInstance() { 34 static HciEventManager sHciEventManager; 35 return sHciEventManager; 36} 37 38void HciEventManager::initialize(nfc_jni_native_data* native) { 39 mNativeData = native; 40 tNFA_STATUS nfaStat = NFA_HciRegister(const_cast<char*>(APP_NAME), 41 (tNFA_HCI_CBACK*)&nfaHciCallback, true); 42 if (nfaStat != NFA_STATUS_OK) { 43 LOG(ERROR) << "HCI registration failed; status=" << nfaStat; 44 } 45 sEsePipe = NfcConfig::getUnsigned(NAME_OFF_HOST_ESE_PIPE_ID, 0x16); 46 sSimPipe = NfcConfig::getUnsigned(NAME_OFF_HOST_SIM_PIPE_ID, 0x0A); 47} 48 49void HciEventManager::notifyTransactionListenersOfAid(std::vector<uint8_t> aid, 50 std::vector<uint8_t> data, 51 std::string evtSrc) { 52 if (aid.empty()) { 53 return; 54 } 55 56 JNIEnv* e = NULL; 57 ScopedAttach attach(mNativeData->vm, &e); 58 CHECK(e); 59 60 ScopedLocalRef<jobject> aidJavaArray(e, e->NewByteArray(aid.size())); 61 CHECK(aidJavaArray.get()); 62 e->SetByteArrayRegion((jbyteArray)aidJavaArray.get(), 0, aid.size(), 63 (jbyte*)&aid[0]); 64 CHECK(!e->ExceptionCheck()); 65 66 ScopedLocalRef<jobject> srcJavaString(e, e->NewStringUTF(evtSrc.c_str())); 67 CHECK(srcJavaString.get()); 68 69 if (data.size() > 0) { 70 ScopedLocalRef<jobject> dataJavaArray(e, e->NewByteArray(data.size())); 71 CHECK(dataJavaArray.get()); 72 e->SetByteArrayRegion((jbyteArray)dataJavaArray.get(), 0, data.size(), 73 (jbyte*)&data[0]); 74 CHECK(!e->ExceptionCheck()); 75 e->CallVoidMethod(mNativeData->manager, 76 android::gCachedNfcManagerNotifyTransactionListeners, 77 aidJavaArray.get(), dataJavaArray.get(), 78 srcJavaString.get()); 79 } else { 80 e->CallVoidMethod(mNativeData->manager, 81 android::gCachedNfcManagerNotifyTransactionListeners, 82 aidJavaArray.get(), NULL, srcJavaString.get()); 83 } 84} 85 86/** 87 * BerTlv has the following format: 88 * 89 * byte1 byte2 byte3 byte4 byte5 byte6 90 * 00-7F - - - - - 91 * 81 00-FF - - - - 92 * 82 0000-FFFF - - - 93 * 83 000000-FFFFFF - - 94 * 84 00000000-FFFFFFFF - 95 */ 96std::vector<uint8_t> HciEventManager::getDataFromBerTlv( 97 std::vector<uint8_t> berTlv) { 98 if (berTlv.empty()) { 99 return std::vector<uint8_t>(); 100 } 101 size_t lengthTag = berTlv[0]; 102 DLOG_IF(INFO, nfc_debug_enabled) << "decodeBerTlv: berTlv[0]=" << berTlv[0]; 103 104 /* As per ISO/IEC 7816, read the first byte to determine the length and 105 * the start index accordingly 106 */ 107 if (lengthTag < 0x80 && berTlv.size() == (lengthTag + 1)) { 108 return std::vector<uint8_t>(berTlv.begin() + 1, berTlv.end()); 109 } else if (lengthTag == 0x81 && berTlv.size() > 2) { 110 size_t length = berTlv[1]; 111 if ((length + 2) == berTlv.size()) { 112 return std::vector<uint8_t>(berTlv.begin() + 2, berTlv.end()); 113 } 114 } else if (lengthTag == 0x82 && berTlv.size() > 3) { 115 size_t length = ((berTlv[1] << 8) | berTlv[2]); 116 if ((length + 3) == berTlv.size()) { 117 return std::vector<uint8_t>(berTlv.begin() + 3, berTlv.end()); 118 } 119 } else if (lengthTag == 0x83 && berTlv.size() > 4) { 120 size_t length = (berTlv[1] << 16) | (berTlv[2] << 8) | berTlv[3]; 121 if ((length + 4) == berTlv.size()) { 122 return std::vector<uint8_t>(berTlv.begin() + 4, berTlv.end()); 123 } 124 } else if (lengthTag == 0x84 && berTlv.size() > 5) { 125 size_t length = 126 (berTlv[1] << 24) | (berTlv[2] << 16) | (berTlv[3] << 8) | berTlv[4]; 127 if ((length + 5) == berTlv.size()) { 128 return std::vector<uint8_t>(berTlv.begin() + 5, berTlv.end()); 129 } 130 } 131 LOG(ERROR) << "Error in TLV length encoding!"; 132 return std::vector<uint8_t>(); 133} 134 135void HciEventManager::nfaHciCallback(tNFA_HCI_EVT event, 136 tNFA_HCI_EVT_DATA* eventData) { 137 if (eventData == nullptr) { 138 return; 139 } 140 141 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 142 "event=%d code=%d pipe=%d len=%d", event, eventData->rcvd_evt.evt_code, 143 eventData->rcvd_evt.pipe, eventData->rcvd_evt.evt_len); 144 145 std::string evtSrc; 146 if (eventData->rcvd_evt.pipe == sEsePipe) { 147 evtSrc = "eSE1"; 148 } else if (eventData->rcvd_evt.pipe == sSimPipe) { 149 evtSrc = "SIM1"; 150 } else { 151 LOG(ERROR) << "Incorrect Pipe Id"; 152 return; 153 } 154 155 uint8_t* buff = eventData->rcvd_evt.p_evt_buf; 156 uint32_t buffLength = eventData->rcvd_evt.evt_len; 157 std::vector<uint8_t> event_buff(buff, buff + buffLength); 158 // Check the event and check if it contains the AID 159 if (event == NFA_HCI_EVENT_RCVD_EVT && 160 eventData->rcvd_evt.evt_code == NFA_HCI_EVT_TRANSACTION && 161 buffLength > 3 && event_buff[0] == 0x81) { 162 int aidlen = event_buff[1]; 163 std::vector<uint8_t> aid(event_buff.begin() + 2, 164 event_buff.begin() + aidlen + 2); 165 166 int32_t berTlvStart = aidlen + 2 + 1; 167 int32_t berTlvLen = buffLength - berTlvStart; 168 std::vector<uint8_t> data; 169 if (berTlvLen > 0 && event_buff[2 + aidlen] == 0x82) { 170 std::vector<uint8_t> berTlv(event_buff.begin() + berTlvStart, 171 event_buff.end()); 172 // BERTLV decoding here, to support extended data length for params. 173 data = getInstance().getDataFromBerTlv(berTlv); 174 } 175 getInstance().notifyTransactionListenersOfAid(aid, data, evtSrc); 176 } 177} 178 179void HciEventManager::finalize() { mNativeData = NULL; } 180