1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 use std::convert::{TryFrom, TryInto};
16
17 use crate::error::{Error, Result};
18 use crate::params::uci_packets::{
19 AppConfigTlv, CapTlv, CoreSetConfigResponse, DeviceConfigTlv, GetDeviceInfoResponse,
20 PowerStats, RawUciMessage, SessionHandle, SessionState,
21 SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse, StatusCode, UciControlPacket,
22 };
23 use crate::uci::error::status_code_to_result;
24
25 #[derive(Debug, Clone, PartialEq)]
26 pub(super) enum UciResponse {
27 SetLoggerMode,
28 SetNotification,
29 OpenHal,
30 CloseHal,
31 DeviceReset(Result<()>),
32 CoreGetDeviceInfo(Result<GetDeviceInfoResponse>),
33 CoreGetCapsInfo(Result<Vec<CapTlv>>),
34 CoreSetConfig(CoreSetConfigResponse),
35 CoreGetConfig(Result<Vec<DeviceConfigTlv>>),
36 SessionInit(Result<Option<SessionHandle>>),
37 SessionDeinit(Result<()>),
38 SessionSetAppConfig(SetAppConfigResponse),
39 SessionGetAppConfig(Result<Vec<AppConfigTlv>>),
40 SessionGetCount(Result<u8>),
41 SessionGetState(Result<SessionState>),
42 SessionUpdateControllerMulticastList(Result<()>),
43 SessionUpdateDtTagRangingRounds(Result<SessionUpdateDtTagRangingRoundsResponse>),
44 SessionQueryMaxDataSize(Result<u16>),
45 SessionStart(Result<()>),
46 SessionStop(Result<()>),
47 SessionGetRangingCount(Result<usize>),
48 AndroidSetCountryCode(Result<()>),
49 AndroidGetPowerStats(Result<PowerStats>),
50 RawUciCmd(Result<RawUciMessage>),
51 SendUciData(Result<()>),
52 }
53
54 impl UciResponse {
need_retry(&self) -> bool55 pub fn need_retry(&self) -> bool {
56 match self {
57 Self::SetNotification | Self::OpenHal | Self::CloseHal | Self::SetLoggerMode => false,
58 Self::DeviceReset(result) => Self::matches_result_retry(result),
59 Self::CoreGetDeviceInfo(result) => Self::matches_result_retry(result),
60 Self::CoreGetCapsInfo(result) => Self::matches_result_retry(result),
61 Self::CoreGetConfig(result) => Self::matches_result_retry(result),
62 Self::SessionInit(result) => Self::matches_result_retry(result),
63 Self::SessionDeinit(result) => Self::matches_result_retry(result),
64 Self::SessionGetAppConfig(result) => Self::matches_result_retry(result),
65 Self::SessionGetCount(result) => Self::matches_result_retry(result),
66 Self::SessionGetState(result) => Self::matches_result_retry(result),
67 Self::SessionUpdateControllerMulticastList(result) => {
68 Self::matches_result_retry(result)
69 }
70 Self::SessionUpdateDtTagRangingRounds(result) => Self::matches_result_retry(result),
71 Self::SessionStart(result) => Self::matches_result_retry(result),
72 Self::SessionStop(result) => Self::matches_result_retry(result),
73 Self::SessionGetRangingCount(result) => Self::matches_result_retry(result),
74 Self::AndroidSetCountryCode(result) => Self::matches_result_retry(result),
75 Self::AndroidGetPowerStats(result) => Self::matches_result_retry(result),
76 Self::RawUciCmd(result) => Self::matches_result_retry(result),
77
78 Self::CoreSetConfig(resp) => Self::matches_status_retry(&resp.status),
79 Self::SessionSetAppConfig(resp) => Self::matches_status_retry(&resp.status),
80
81 Self::SessionQueryMaxDataSize(result) => Self::matches_result_retry(result),
82 // TODO(b/273376343): Implement retry logic for Data packet send.
83 Self::SendUciData(_result) => false,
84 }
85 }
86
matches_result_retry<T>(result: &Result<T>) -> bool87 fn matches_result_retry<T>(result: &Result<T>) -> bool {
88 matches!(result, Err(Error::CommandRetry))
89 }
matches_status_retry(status: &StatusCode) -> bool90 fn matches_status_retry(status: &StatusCode) -> bool {
91 matches!(status, StatusCode::UciStatusCommandRetry)
92 }
93 }
94
95 impl TryFrom<uwb_uci_packets::UciResponse> for UciResponse {
96 type Error = Error;
try_from(evt: uwb_uci_packets::UciResponse) -> std::result::Result<Self, Self::Error>97 fn try_from(evt: uwb_uci_packets::UciResponse) -> std::result::Result<Self, Self::Error> {
98 use uwb_uci_packets::UciResponseChild;
99 match evt.specialize() {
100 UciResponseChild::CoreResponse(evt) => evt.try_into(),
101 UciResponseChild::SessionConfigResponse(evt) => evt.try_into(),
102 UciResponseChild::SessionControlResponse(evt) => evt.try_into(),
103 UciResponseChild::AndroidResponse(evt) => evt.try_into(),
104 UciResponseChild::UciVendor_9_Response(evt) => raw_response(evt.into()),
105 UciResponseChild::UciVendor_A_Response(evt) => raw_response(evt.into()),
106 UciResponseChild::UciVendor_B_Response(evt) => raw_response(evt.into()),
107 UciResponseChild::UciVendor_E_Response(evt) => raw_response(evt.into()),
108 UciResponseChild::UciVendor_F_Response(evt) => raw_response(evt.into()),
109 _ => Err(Error::Unknown),
110 }
111 }
112 }
113
114 impl TryFrom<uwb_uci_packets::CoreResponse> for UciResponse {
115 type Error = Error;
try_from(evt: uwb_uci_packets::CoreResponse) -> std::result::Result<Self, Self::Error>116 fn try_from(evt: uwb_uci_packets::CoreResponse) -> std::result::Result<Self, Self::Error> {
117 use uwb_uci_packets::CoreResponseChild;
118 match evt.specialize() {
119 CoreResponseChild::GetDeviceInfoRsp(evt) => Ok(UciResponse::CoreGetDeviceInfo(
120 status_code_to_result(evt.get_status()).map(|_| GetDeviceInfoResponse {
121 uci_version: evt.get_uci_version(),
122 mac_version: evt.get_mac_version(),
123 phy_version: evt.get_phy_version(),
124 uci_test_version: evt.get_uci_test_version(),
125 vendor_spec_info: evt.get_vendor_spec_info().clone(),
126 }),
127 )),
128 CoreResponseChild::GetCapsInfoRsp(evt) => Ok(UciResponse::CoreGetCapsInfo(
129 status_code_to_result(evt.get_status()).map(|_| evt.get_tlvs().clone()),
130 )),
131 CoreResponseChild::DeviceResetRsp(evt) => {
132 Ok(UciResponse::DeviceReset(status_code_to_result(evt.get_status())))
133 }
134 CoreResponseChild::SetConfigRsp(evt) => {
135 Ok(UciResponse::CoreSetConfig(CoreSetConfigResponse {
136 status: evt.get_status(),
137 config_status: evt.get_cfg_status().clone(),
138 }))
139 }
140
141 CoreResponseChild::GetConfigRsp(evt) => Ok(UciResponse::CoreGetConfig(
142 status_code_to_result(evt.get_status()).map(|_| evt.get_tlvs().clone()),
143 )),
144 _ => Err(Error::Unknown),
145 }
146 }
147 }
148
149 impl TryFrom<uwb_uci_packets::SessionConfigResponse> for UciResponse {
150 type Error = Error;
try_from( evt: uwb_uci_packets::SessionConfigResponse, ) -> std::result::Result<Self, Self::Error>151 fn try_from(
152 evt: uwb_uci_packets::SessionConfigResponse,
153 ) -> std::result::Result<Self, Self::Error> {
154 use uwb_uci_packets::SessionConfigResponseChild;
155 match evt.specialize() {
156 SessionConfigResponseChild::SessionInitRsp(evt) => {
157 Ok(UciResponse::SessionInit(status_code_to_result(evt.get_status()).map(|_| None)))
158 }
159 SessionConfigResponseChild::SessionInitRsp_V2(evt) => Ok(UciResponse::SessionInit(
160 status_code_to_result(evt.get_status()).map(|_| Some(evt.get_session_handle())),
161 )),
162 SessionConfigResponseChild::SessionDeinitRsp(evt) => {
163 Ok(UciResponse::SessionDeinit(status_code_to_result(evt.get_status())))
164 }
165 SessionConfigResponseChild::SessionGetCountRsp(evt) => {
166 Ok(UciResponse::SessionGetCount(
167 status_code_to_result(evt.get_status()).map(|_| evt.get_session_count()),
168 ))
169 }
170 SessionConfigResponseChild::SessionGetStateRsp(evt) => {
171 Ok(UciResponse::SessionGetState(
172 status_code_to_result(evt.get_status()).map(|_| evt.get_session_state()),
173 ))
174 }
175 SessionConfigResponseChild::SessionUpdateControllerMulticastListRsp(evt) => {
176 Ok(UciResponse::SessionUpdateControllerMulticastList(status_code_to_result(
177 evt.get_status(),
178 )))
179 }
180 SessionConfigResponseChild::SessionUpdateDtTagRangingRoundsRsp(evt) => {
181 Ok(UciResponse::SessionUpdateDtTagRangingRounds(Ok(
182 SessionUpdateDtTagRangingRoundsResponse {
183 status: evt.get_status(),
184 ranging_round_indexes: evt.get_ranging_round_indexes().to_vec(),
185 },
186 )))
187 }
188 SessionConfigResponseChild::SessionSetAppConfigRsp(evt) => {
189 Ok(UciResponse::SessionSetAppConfig(SetAppConfigResponse {
190 status: evt.get_status(),
191 config_status: evt.get_cfg_status().clone(),
192 }))
193 }
194 SessionConfigResponseChild::SessionGetAppConfigRsp(evt) => {
195 Ok(UciResponse::SessionGetAppConfig(
196 status_code_to_result(evt.get_status()).map(|_| {
197 evt.get_tlvs().clone().into_iter().map(|tlv| tlv.into()).collect()
198 }),
199 ))
200 }
201 SessionConfigResponseChild::SessionQueryMaxDataSizeRsp(evt) => {
202 Ok(UciResponse::SessionQueryMaxDataSize(Ok(evt.get_max_data_size())))
203 }
204 _ => Err(Error::Unknown),
205 }
206 }
207 }
208
209 impl TryFrom<uwb_uci_packets::SessionControlResponse> for UciResponse {
210 type Error = Error;
try_from( evt: uwb_uci_packets::SessionControlResponse, ) -> std::result::Result<Self, Self::Error>211 fn try_from(
212 evt: uwb_uci_packets::SessionControlResponse,
213 ) -> std::result::Result<Self, Self::Error> {
214 use uwb_uci_packets::SessionControlResponseChild;
215 match evt.specialize() {
216 SessionControlResponseChild::SessionStartRsp(evt) => {
217 Ok(UciResponse::SessionStart(status_code_to_result(evt.get_status())))
218 }
219 SessionControlResponseChild::SessionStopRsp(evt) => {
220 Ok(UciResponse::SessionStop(status_code_to_result(evt.get_status())))
221 }
222 SessionControlResponseChild::SessionGetRangingCountRsp(evt) => {
223 Ok(UciResponse::SessionGetRangingCount(
224 status_code_to_result(evt.get_status()).map(|_| evt.get_count() as usize),
225 ))
226 }
227 _ => Err(Error::Unknown),
228 }
229 }
230 }
231
232 impl TryFrom<uwb_uci_packets::AndroidResponse> for UciResponse {
233 type Error = Error;
try_from(evt: uwb_uci_packets::AndroidResponse) -> std::result::Result<Self, Self::Error>234 fn try_from(evt: uwb_uci_packets::AndroidResponse) -> std::result::Result<Self, Self::Error> {
235 use uwb_uci_packets::AndroidResponseChild;
236 match evt.specialize() {
237 AndroidResponseChild::AndroidSetCountryCodeRsp(evt) => {
238 Ok(UciResponse::AndroidSetCountryCode(status_code_to_result(evt.get_status())))
239 }
240 AndroidResponseChild::AndroidGetPowerStatsRsp(evt) => {
241 Ok(UciResponse::AndroidGetPowerStats(
242 status_code_to_result(evt.get_stats().status).map(|_| evt.get_stats().clone()),
243 ))
244 }
245 _ => Err(Error::Unknown),
246 }
247 }
248 }
249
raw_response(evt: uwb_uci_packets::UciResponse) -> Result<UciResponse>250 fn raw_response(evt: uwb_uci_packets::UciResponse) -> Result<UciResponse> {
251 let gid: u32 = evt.get_group_id().into();
252 let oid: u32 = evt.get_opcode().into();
253 let packet: UciControlPacket = evt.into();
254 Ok(UciResponse::RawUciCmd(Ok(RawUciMessage { gid, oid, payload: packet.to_raw_payload() })))
255 }
256