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
hal_nci_send(tNFC_NCI_PKT * pkt)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
hal_nci_send_reset(void)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]
hal_nci_send_init(int version)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 */
hal_nci_send_clearLmrt(void)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
get_clock_info(int rev,int field_name,int * buffer)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
hal_nci_send_prop_fw_cfg(void)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
nci_read_payload(tNFC_HAL_MSG * msg)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
fw_force_update(void * param)142 void fw_force_update(__attribute__((unused)) void* param) {
143 OSI_loge("need to F/W update!");
144 }
145
nci_init_timeout(void * param)146 void nci_init_timeout(__attribute__((unused)) void* param) {
147 OSI_loge("need to retry!");
148 }
149
nfc_hal_prehandler(tNFC_NCI_PKT * pkt)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