1 /* 2 * Copyright (C) 2013 SAMSUNG S.LSI 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 * 17 */ 18 19 #include <hardware/nfc.h> 20 #include <string.h> 21 22 #include "device.h" 23 #include "hal.h" 24 #include "hal_msg.h" 25 #include "osi.h" 26 #include "util.h" 27 28 int hal_nci_send(tNFC_NCI_PKT* pkt) { 29 size_t len = (size_t)(pkt->len + NCI_HDR_SIZE); 30 int ret; 31 32 ret = __send_to_device((uint8_t*)pkt, len); 33 if (ret != (int)len 34 /* workaround for retry; F/W I2C issue */ 35 && (nfc_hal_info.flag & HAL_FLAG_NTF_TRNS_ERROR)) { 36 OSI_loge("NCI message send failed"); 37 OSI_logd("set flag to 0x%06X", nfc_hal_info.flag); 38 } else { 39 util_nci_analyzer(pkt); 40 } 41 42 return ret; 43 } 44 45 void hal_nci_send_reset(void) { 46 tNFC_NCI_PKT nci_pkt; 47 48 memset(&nci_pkt, 0, sizeof(tNFC_NCI_PKT)); 49 nci_pkt.oct0 = NCI_MT_CMD | NCI_PBF_LAST | NCI_GID_CORE; 50 nci_pkt.oid = NCI_CORE_RESET; 51 nci_pkt.len = 0x01; 52 nci_pkt.payload[0] = 0x01; // Reset config 53 54 hal_nci_send(&nci_pkt); 55 } 56 57 /* START [181106] Patch for supporting NCI v2.0 */ 58 // [3. CORE_INIT Changes] 59 void hal_nci_send_init(int version) { 60 /* END [181106] Patch for supporting NCI v2.0 */ 61 tNFC_NCI_PKT nci_pkt; 62 63 /* START [181106] Patch for supporting NCI v2.0 */ 64 //[3. CORE_INIT Changes] 65 memset(&nci_pkt, 0, sizeof(tNFC_NCI_PKT)); 66 nci_pkt.oct0 = NCI_MT_CMD | NCI_PBF_LAST | NCI_GID_CORE; 67 nci_pkt.oid = NCI_CORE_INIT; 68 nci_pkt.len = 0x00; 69 70 if (version == NCI_VER_2_0) { 71 nci_pkt.len = 0x02; 72 nci_pkt.payload[0] = 0x00; 73 nci_pkt.payload[1] = 0x00; 74 } 75 /* END [181106] Patch for supporting NCI v2.0 */ 76 77 hal_nci_send(&nci_pkt); 78 } 79 80 /* Workaround: Initialization flash of LMRT */ 81 void hal_nci_send_clearLmrt(void) { 82 tNFC_NCI_PKT nci_pkt; 83 84 memset(&nci_pkt, 0, sizeof(tNFC_NCI_PKT)); 85 nci_pkt.oct0 = NCI_MT_CMD | NCI_PBF_LAST | NCI_GID_RF_MANAGE; 86 nci_pkt.oid = 0x01; // RF_SET_LMRT 87 nci_pkt.len = 0x02; 88 nci_pkt.payload[0] = 0x00; 89 nci_pkt.payload[1] = 0x00; 90 91 hal_nci_send(&nci_pkt); 92 } 93 /* END WA */ 94 95 void get_clock_info(int rev, int field_name, int* buffer) { 96 char rev_field[50] = { 97 '\0', 98 }; 99 int isRevField = 0; 100 101 sprintf(rev_field, "%s_REV%d", cfg_name_table[field_name], rev); 102 isRevField = get_config_count(rev_field); 103 if (rev >= 0 && isRevField) { 104 if (!get_config_int(rev_field, buffer)) *buffer = 0; 105 } else if (!get_config_int(cfg_name_table[field_name], buffer)) 106 *buffer = 0; 107 } 108 109 void hal_nci_send_prop_fw_cfg(void) { 110 tNFC_NCI_PKT nci_pkt; 111 int rev = get_hw_rev(); 112 113 memset(&nci_pkt, 0, sizeof(tNFC_NCI_PKT)); 114 nci_pkt.oct0 = NCI_MT_CMD | NCI_PBF_LAST | NCI_GID_PROP; 115 nci_pkt.oid = NCI_PROP_FW_CFG; 116 117 nci_pkt.len = 0x01; 118 get_clock_info(rev, CFG_FW_CLK_SPEED, (int*)&nci_pkt.payload[0]); 119 if (nci_pkt.payload[0] == 0xff) { 120 OSI_loge("Set a different value! Current Clock Speed Value : 0x%x", 121 nci_pkt.payload[0]); 122 return; 123 } 124 hal_nci_send(&nci_pkt); 125 } 126 127 int nci_read_payload(tNFC_HAL_MSG* msg) { 128 tNFC_NCI_PKT* pkt = &msg->nci_packet; 129 int ret; 130 131 ret = device_read(NCI_PAYLOAD(pkt), NCI_LEN(pkt)); 132 if (ret != (int)NCI_LEN(pkt)) { 133 OSI_mem_free((tOSI_MEM_HANDLER)msg); 134 OSI_loge("Failed to read payload"); 135 return ret; 136 } 137 138 data_trace("Recv", NCI_HDR_SIZE + ret, msg->param); 139 return ret; 140 } 141 142 void fw_force_update(__attribute__((unused)) void* param) { 143 OSI_loge("need to F/W update!"); 144 } 145 146 void nci_init_timeout(__attribute__((unused)) void* param) { 147 OSI_loge("need to retry!"); 148 } 149 150 bool nfc_hal_prehandler(tNFC_NCI_PKT* pkt) { 151 if (NCI_MT(pkt) == NCI_MT_NTF) { 152 if (NCI_GID(pkt) == NCI_GID_PROP) { 153 /* Again procedure. only for N3 isN3group */ 154 if (NCI_OID(pkt) == NCI_PROP_AGAIN) { 155 if (nfc_hal_info.nci_last_pkt) { 156 OSI_logd("NFC requests sending last message again!"); 157 hal_update_sleep_timer(); 158 device_write((uint8_t*)nfc_hal_info.nci_last_pkt, 159 (size_t)(nfc_hal_info.nci_last_pkt->len + NCI_HDR_SIZE)); 160 return false; 161 } 162 } 163 } 164 } 165 166 if (NCI_MT(pkt) == NCI_MT_CMD) { 167 if (NCI_GID(pkt) == NCI_GID_PROP) { 168 if (NCI_OID(pkt) == NCI_PROP_WR_RESET) { 169 hal_nci_send_reset(); 170 nfc_hal_info.flag |= HAL_FLAG_PROP_RESET; 171 return false; 172 } 173 174 if (NCI_OID(pkt) == NCI_PROP_SET_SLEEP_TIME) { 175 tNFC_NCI_PKT dummy_rsp; 176 dummy_rsp.oct0 = NCI_MT_RSP | NCI_PBF_LAST | NCI_GID_PROP; 177 dummy_rsp.oid = NCI_OID(pkt); 178 dummy_rsp.len = 1; 179 dummy_rsp.payload[0] = NCI_STATUS_OK; 180 181 if (NCI_LEN(pkt) == 0) { 182 setSleepTimeout(SET_SLEEP_TIME_CFG, 5000); 183 } else { 184 uint32_t timeout = NCI_PAYLOAD(pkt)[0] * 1000; // sec 185 int option = SET_SLEEP_TIME_ONCE; 186 187 if (NCI_LEN(pkt) > 1) 188 timeout += NCI_PAYLOAD(pkt)[1] * 1000 * 60; // min 189 190 if (NCI_LEN(pkt) > 2) option = NCI_PAYLOAD(pkt)[2]; 191 192 setSleepTimeout(option, timeout); 193 } 194 195 hal_update_sleep_timer(); 196 nfc_data_callback(&dummy_rsp); 197 return false; 198 } 199 } 200 } 201 202 if (NCI_MT(pkt) == NCI_MT_RSP) { 203 if (NCI_GID(pkt) == NCI_GID_CORE) { 204 if (NCI_OID(pkt) == NCI_CORE_RESET) { 205 pkt->oct0 = NCI_MT_RSP | NCI_PBF_LAST | NCI_GID_PROP; 206 pkt->oid = NCI_PROP_WR_RESET; 207 } 208 } 209 } 210 return true; 211 } 212