1 /******************************************************************************
2 *
3 * Copyright (C) 2023 The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains the action functions the NFA_WLC state machine.
22 *
23 ******************************************************************************/
24 #include <android-base/logging.h>
25 #include <android-base/stringprintf.h>
26 #include <log/log.h>
27 #include <string.h>
28
29 #include "nfa_dm_int.h"
30 #include "nfa_rw_int.h"
31 #include "nfa_wlc_int.h"
32
33 using android::base::StringPrintf;
34
35 /*******************************************************************************
36 **
37 ** Function nfa_wlc_enable
38 **
39 ** Description Initialize the NFC WLC manager
40 **
41 ** Returns TRUE (message buffer to be freed by caller)
42 **
43 *******************************************************************************/
nfa_wlc_enable(tNFA_WLC_MSG * p_data)44 bool nfa_wlc_enable(tNFA_WLC_MSG* p_data) {
45 LOG(VERBOSE) << StringPrintf("%s; nfa_dm_cb.flags=0x%x", __func__,
46 nfa_dm_cb.flags);
47 tNFA_WLC_EVT_DATA wlc_cback_data;
48
49 /* Check if NFA is already enabled */
50 if ((nfa_dm_cb.flags & NFA_DM_FLAGS_DM_IS_ACTIVE) &&
51 !((nfa_dm_cb.flags & NFA_DM_FLAGS_ENABLE_EVT_PEND) ||
52 (nfa_dm_cb.flags & NFA_DM_FLAGS_DM_DISABLING_NFC))) {
53 /* Store Enable parameters */
54 nfa_wlc_cb.p_wlc_cback = p_data->enable.p_wlc_cback;
55
56 wlc_cback_data.status = NFA_STATUS_OK;
57 } else {
58 LOG(VERBOSE) << StringPrintf(
59 "%s; DM not active or enable event pending or DM disabling NFC ",
60 __func__);
61 wlc_cback_data.status = NFA_STATUS_FAILED;
62 }
63 (*(p_data->enable.p_wlc_cback))(NFA_WLC_ENABLE_RESULT_EVT, &wlc_cback_data);
64
65 return true;
66 }
67
68 /*******************************************************************************
69 **
70 ** Function nfa_wlc_start
71 **
72 ** Description Start WLC-P Non-Autonomous RF Interface Extension
73 ** if conditions are met (extension supported by NFCC,
74 ** NFCC in POLL_ACTIVE, correct protocol for activated tag,
75 ** DM module in appropriate state...).
76 **
77 ** Returns TRUE upon successful start else FALSE
78 **
79 *******************************************************************************/
nfa_wlc_start(tNFA_WLC_MSG * p_data)80 bool nfa_wlc_start(tNFA_WLC_MSG* p_data) {
81 LOG(VERBOSE) << StringPrintf("%s; ", __func__);
82
83 /* If mode is WLC-P Non-Autonomous mode:
84 * Support for WLC-P Non-Autonomous RF Interface Extension in CORE_INIT_RSP
85 * mandated Non-Autonomous RF Frame Extension shall be in stopped state NFCC
86 * in RFST_POLL_ACTIVE Frame RF or ISO-DEP Interfaces shall be in activated
87 * state EP protocol: T2T, T3T, T5T, ISO-DEP DH not waiting for a response
88 * from the EP
89 */
90
91 if (p_data->start.mode == NFA_WLC_NON_AUTONOMOUS) {
92 // TODO: check WLC-P Non-Autonomous RF Interface Extension is enabled in
93 // CORE_INIT_RSP
94
95 if (nfa_wlc_cb.flags & NFA_WLC_FLAGS_NON_AUTO_MODE_ENABLED) {
96 /* Non-Autonomous RF Frame Extension shall be in stopped state */
97 /* return status not stopped to JNI ???*/
98 LOG(ERROR) << StringPrintf(
99 "%s; WLCP Non-autonomous Extension not "
100 "in stopped state",
101 __func__);
102 return false;
103 }
104
105 if (nfa_dm_cb.disc_cb.disc_state != NFA_DM_RFST_POLL_ACTIVE) {
106 LOG(ERROR) << StringPrintf(
107 "%s; NFCC not in WLCP "
108 "RFST_POLL_ACTIVE state",
109 __func__);
110 return false;
111 }
112
113 if (!((nfa_rw_cb.protocol == NFC_PROTOCOL_T2T) ||
114 (nfa_rw_cb.protocol == NFC_PROTOCOL_T3T) ||
115 (nfa_rw_cb.protocol == NFC_PROTOCOL_T5T) ||
116 (nfa_rw_cb.protocol == NFA_PROTOCOL_ISO_DEP))) {
117 LOG(ERROR) << StringPrintf("%s; Invalid RF protocol activated", __func__);
118 return false;
119 }
120
121 if (nfa_rw_cb.flags & NFA_RW_FL_API_BUSY) {
122 LOG(ERROR) << StringPrintf("%s; RW API already busy", __func__);
123 /* TODO: pending till RW action completes? */
124 return false;
125 }
126 if (nfa_dm_cb.disc_cb.disc_flags &
127 (NFA_DM_DISC_FLAGS_W4_RSP | NFA_DM_DISC_FLAGS_W4_NTF |
128 NFA_DM_DISC_FLAGS_STOPPING | /* Stop RF discovery is pending */
129 NFA_DM_DISC_FLAGS_DISABLING)) /* Disable NFA is pending */
130 {
131 // TODO: shall we check other modules busy?
132 return false;
133 }
134
135 nfa_wlc_cb.wlc_mode = p_data->start.mode;
136
137 // TODO: remove as only for testing, replace by extension activation
138 nfa_dm_cb.flags |= NFA_DM_FLAGS_RF_EXT_ACTIVE;
139 nfa_dm_cb.flags |= NFA_DM_FLAGS_WLCP_ENABLED;
140
141 tNFA_WLC_EVT_DATA wlc_cback_data;
142 wlc_cback_data.status = NFA_STATUS_OK;
143 nfa_wlc_event_notify(NFA_WLC_START_RESULT_EVT, &wlc_cback_data);
144
145 return true;
146
147 } else {
148 LOG(ERROR) << StringPrintf("%s; Wireless Charging mode not supported",
149 __func__);
150 return false;
151 }
152 }
153
154 /*******************************************************************************
155 **
156 ** Function nfa_wlc_non_auto_start_wpt
157 **
158 ** Description Stop timer for presence check
159 **
160 ** Returns Nothing
161 **
162 *******************************************************************************/
nfa_wlc_non_auto_start_wpt(tNFA_WLC_MSG * p_data)163 bool nfa_wlc_non_auto_start_wpt(tNFA_WLC_MSG* p_data) {
164 LOG(VERBOSE) << StringPrintf("%s; power_adj_req=0x%x, wpt_time_int=0x%x",
165 __func__, p_data->non_auto_start_wpt.power_adj_req,
166 p_data->non_auto_start_wpt.wpt_time_int);
167
168 nfa_dm_start_wireless_power_transfer(p_data->non_auto_start_wpt.power_adj_req,
169 p_data->non_auto_start_wpt.wpt_time_int);
170
171 return true;
172 }
173