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 log::error;
18
19 use crate::error::{Error, Result};
20 use crate::params::uci_packets::{
21 AndroidRadarConfigResponse, AppConfigTlv, CapTlv, CoreSetConfigResponse, DeviceConfigTlv,
22 GetDeviceInfoResponse, PowerStats, RadarConfigTlv, RawUciMessage, SessionHandle, SessionState,
23 SessionUpdateControllerMulticastListRspV1Payload,
24 SessionUpdateControllerMulticastListRspV2Payload, SessionUpdateControllerMulticastResponse,
25 SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse, StatusCode, UCIMajorVersion,
26 UciControlPacket,
27 };
28 use crate::uci::error::status_code_to_result;
29
30 #[derive(Debug, Clone, PartialEq)]
31 pub(super) enum UciResponse {
32 SetLoggerMode,
33 SetNotification,
34 OpenHal,
35 CloseHal,
36 DeviceReset(Result<()>),
37 CoreGetDeviceInfo(Result<GetDeviceInfoResponse>),
38 CoreGetCapsInfo(Result<Vec<CapTlv>>),
39 CoreSetConfig(CoreSetConfigResponse),
40 CoreGetConfig(Result<Vec<DeviceConfigTlv>>),
41 CoreQueryTimeStamp(Result<u64>),
42 SessionInit(Result<Option<SessionHandle>>),
43 SessionDeinit(Result<()>),
44 SessionSetAppConfig(SetAppConfigResponse),
45 SessionGetAppConfig(Result<Vec<AppConfigTlv>>),
46 SessionGetCount(Result<u8>),
47 SessionGetState(Result<SessionState>),
48 SessionUpdateControllerMulticastList(Result<SessionUpdateControllerMulticastResponse>),
49 SessionUpdateDtTagRangingRounds(Result<SessionUpdateDtTagRangingRoundsResponse>),
50 SessionQueryMaxDataSize(Result<u16>),
51 SessionStart(Result<()>),
52 SessionStop(Result<()>),
53 SessionGetRangingCount(Result<usize>),
54 AndroidSetCountryCode(Result<()>),
55 AndroidGetPowerStats(Result<PowerStats>),
56 AndroidSetRadarConfig(AndroidRadarConfigResponse),
57 AndroidGetRadarConfig(Result<Vec<RadarConfigTlv>>),
58 RawUciCmd(Result<RawUciMessage>),
59 SendUciData(Result<()>),
60 SessionSetHybridControllerConfig(Result<()>),
61 SessionSetHybridControleeConfig(Result<()>),
62 SessionDataTransferPhaseConfig(Result<()>),
63 }
64
65 impl UciResponse {
need_retry(&self) -> bool66 pub fn need_retry(&self) -> bool {
67 match self {
68 Self::SetNotification | Self::OpenHal | Self::CloseHal | Self::SetLoggerMode => false,
69 Self::DeviceReset(result) => Self::matches_result_retry(result),
70 Self::CoreGetDeviceInfo(result) => Self::matches_result_retry(result),
71 Self::CoreGetCapsInfo(result) => Self::matches_result_retry(result),
72 Self::CoreGetConfig(result) => Self::matches_result_retry(result),
73 Self::CoreQueryTimeStamp(result) => Self::matches_result_retry(result),
74 Self::SessionInit(result) => Self::matches_result_retry(result),
75 Self::SessionDeinit(result) => Self::matches_result_retry(result),
76 Self::SessionGetAppConfig(result) => Self::matches_result_retry(result),
77 Self::SessionGetCount(result) => Self::matches_result_retry(result),
78 Self::SessionGetState(result) => Self::matches_result_retry(result),
79 Self::SessionUpdateControllerMulticastList(result) => {
80 Self::matches_result_retry(result)
81 }
82 Self::SessionUpdateDtTagRangingRounds(result) => Self::matches_result_retry(result),
83 Self::SessionStart(result) => Self::matches_result_retry(result),
84 Self::SessionStop(result) => Self::matches_result_retry(result),
85 Self::SessionGetRangingCount(result) => Self::matches_result_retry(result),
86 Self::AndroidSetCountryCode(result) => Self::matches_result_retry(result),
87 Self::AndroidGetPowerStats(result) => Self::matches_result_retry(result),
88 Self::AndroidGetRadarConfig(result) => Self::matches_result_retry(result),
89 Self::AndroidSetRadarConfig(resp) => Self::matches_status_retry(&resp.status),
90 Self::RawUciCmd(result) => Self::matches_result_retry(result),
91 Self::SessionSetHybridControllerConfig(result) => Self::matches_result_retry(result),
92 Self::SessionSetHybridControleeConfig(result) => Self::matches_result_retry(result),
93 Self::SessionDataTransferPhaseConfig(result) => Self::matches_result_retry(result),
94 Self::CoreSetConfig(resp) => Self::matches_status_retry(&resp.status),
95 Self::SessionSetAppConfig(resp) => Self::matches_status_retry(&resp.status),
96
97 Self::SessionQueryMaxDataSize(result) => Self::matches_result_retry(result),
98 // TODO(b/273376343): Implement retry logic for Data packet send.
99 Self::SendUciData(_result) => false,
100 }
101 }
102
matches_result_retry<T>(result: &Result<T>) -> bool103 fn matches_result_retry<T>(result: &Result<T>) -> bool {
104 matches!(result, Err(Error::CommandRetry))
105 }
matches_status_retry(status: &StatusCode) -> bool106 fn matches_status_retry(status: &StatusCode) -> bool {
107 matches!(status, StatusCode::UciStatusCommandRetry)
108 }
109 }
110
111 impl TryFrom<(uwb_uci_packets::UciResponse, UCIMajorVersion, bool)> for UciResponse {
112 type Error = Error;
try_from( pair: (uwb_uci_packets::UciResponse, UCIMajorVersion, bool), ) -> std::result::Result<Self, Self::Error>113 fn try_from(
114 pair: (uwb_uci_packets::UciResponse, UCIMajorVersion, bool),
115 ) -> std::result::Result<Self, Self::Error> {
116 let evt = pair.0;
117 let uci_fira_major_ver = pair.1;
118 let is_multicast_list_rsp_v2_supported = pair.2;
119 use uwb_uci_packets::UciResponseChild;
120 match evt.specialize() {
121 UciResponseChild::CoreResponse(evt) => evt.try_into(),
122 UciResponseChild::SessionConfigResponse(evt) => {
123 (evt, uci_fira_major_ver, is_multicast_list_rsp_v2_supported).try_into()
124 }
125 UciResponseChild::SessionControlResponse(evt) => evt.try_into(),
126 UciResponseChild::AndroidResponse(evt) => evt.try_into(),
127 UciResponseChild::UciVendor_9_Response(evt) => raw_response(evt.into()),
128 UciResponseChild::UciVendor_A_Response(evt) => raw_response(evt.into()),
129 UciResponseChild::UciVendor_B_Response(evt) => raw_response(evt.into()),
130 UciResponseChild::UciVendor_E_Response(evt) => raw_response(evt.into()),
131 UciResponseChild::UciVendor_F_Response(evt) => raw_response(evt.into()),
132 _ => Err(Error::Unknown),
133 }
134 }
135 }
136
137 impl TryFrom<uwb_uci_packets::CoreResponse> for UciResponse {
138 type Error = Error;
try_from(evt: uwb_uci_packets::CoreResponse) -> std::result::Result<Self, Self::Error>139 fn try_from(evt: uwb_uci_packets::CoreResponse) -> std::result::Result<Self, Self::Error> {
140 use uwb_uci_packets::CoreResponseChild;
141 match evt.specialize() {
142 CoreResponseChild::GetDeviceInfoRsp(evt) => Ok(UciResponse::CoreGetDeviceInfo(
143 status_code_to_result(evt.get_status()).map(|_| GetDeviceInfoResponse {
144 status: evt.get_status(),
145 uci_version: evt.get_uci_version(),
146 mac_version: evt.get_mac_version(),
147 phy_version: evt.get_phy_version(),
148 uci_test_version: evt.get_uci_test_version(),
149 vendor_spec_info: evt.get_vendor_spec_info().clone(),
150 }),
151 )),
152 CoreResponseChild::GetCapsInfoRsp(evt) => Ok(UciResponse::CoreGetCapsInfo(
153 status_code_to_result(evt.get_status()).map(|_| evt.get_tlvs().clone()),
154 )),
155 CoreResponseChild::DeviceResetRsp(evt) => {
156 Ok(UciResponse::DeviceReset(status_code_to_result(evt.get_status())))
157 }
158 CoreResponseChild::SetConfigRsp(evt) => {
159 Ok(UciResponse::CoreSetConfig(CoreSetConfigResponse {
160 status: evt.get_status(),
161 config_status: evt.get_cfg_status().clone(),
162 }))
163 }
164
165 CoreResponseChild::GetConfigRsp(evt) => Ok(UciResponse::CoreGetConfig(
166 status_code_to_result(evt.get_status()).map(|_| evt.get_tlvs().clone()),
167 )),
168 CoreResponseChild::CoreQueryTimeStampRsp(evt) => Ok(UciResponse::CoreQueryTimeStamp(
169 status_code_to_result(evt.get_status()).map(|_| evt.get_timeStamp()),
170 )),
171 _ => Err(Error::Unknown),
172 }
173 }
174 }
175
176 impl TryFrom<(uwb_uci_packets::SessionConfigResponse, UCIMajorVersion, bool)> for UciResponse {
177 type Error = Error;
try_from( pair: (uwb_uci_packets::SessionConfigResponse, UCIMajorVersion, bool), ) -> std::result::Result<Self, Self::Error>178 fn try_from(
179 pair: (uwb_uci_packets::SessionConfigResponse, UCIMajorVersion, bool),
180 ) -> std::result::Result<Self, Self::Error> {
181 use uwb_uci_packets::SessionConfigResponseChild;
182 let evt = pair.0;
183 let uci_fira_major_ver = pair.1;
184 let is_multicast_list_rsp_v2_supported = pair.2;
185 match evt.specialize() {
186 SessionConfigResponseChild::SessionInitRsp(evt) => {
187 Ok(UciResponse::SessionInit(status_code_to_result(evt.get_status()).map(|_| None)))
188 }
189 SessionConfigResponseChild::SessionInitRsp_V2(evt) => Ok(UciResponse::SessionInit(
190 status_code_to_result(evt.get_status()).map(|_| Some(evt.get_session_handle())),
191 )),
192 SessionConfigResponseChild::SessionDeinitRsp(evt) => {
193 Ok(UciResponse::SessionDeinit(status_code_to_result(evt.get_status())))
194 }
195 SessionConfigResponseChild::SessionGetCountRsp(evt) => {
196 Ok(UciResponse::SessionGetCount(
197 status_code_to_result(evt.get_status()).map(|_| evt.get_session_count()),
198 ))
199 }
200 SessionConfigResponseChild::SessionGetStateRsp(evt) => {
201 Ok(UciResponse::SessionGetState(
202 status_code_to_result(evt.get_status()).map(|_| evt.get_session_state()),
203 ))
204 }
205 SessionConfigResponseChild::SessionUpdateControllerMulticastListRsp(evt)
206 if uci_fira_major_ver == UCIMajorVersion::V1
207 || !is_multicast_list_rsp_v2_supported =>
208 {
209 error!(
210 "Tryfrom: SessionConfigResponse:: SessionUpdateControllerMulticastListRspV1 "
211 );
212 let payload = evt.get_payload();
213 let multicast_update_list_rsp_payload_v1 =
214 SessionUpdateControllerMulticastListRspV1Payload::parse(payload).map_err(
215 |e| {
216 error!(
217 "Failed to parse Multicast list ntf v1 {:?}, payload: {:?}",
218 e, &payload
219 );
220 Error::BadParameters
221 },
222 )?;
223
224 Ok(UciResponse::SessionUpdateControllerMulticastList(Ok(
225 SessionUpdateControllerMulticastResponse {
226 status: multicast_update_list_rsp_payload_v1.status,
227 status_list: vec![],
228 },
229 )))
230 }
231 SessionConfigResponseChild::SessionUpdateControllerMulticastListRsp(evt)
232 if uci_fira_major_ver == UCIMajorVersion::V2 =>
233 {
234 error!(
235 "Tryfrom: SessionConfigResponse:: SessionUpdateControllerMulticastListRspV2 "
236 );
237 let payload = evt.get_payload();
238 let multicast_update_list_rsp_payload_v2 =
239 SessionUpdateControllerMulticastListRspV2Payload::parse(payload).map_err(
240 |e| {
241 error!(
242 "Failed to parse Multicast list ntf v1 {:?}, payload: {:?}",
243 e, &payload
244 );
245 Error::BadParameters
246 },
247 )?;
248 Ok(UciResponse::SessionUpdateControllerMulticastList(Ok(
249 SessionUpdateControllerMulticastResponse {
250 status: multicast_update_list_rsp_payload_v2.status,
251 status_list: multicast_update_list_rsp_payload_v2.controlee_status,
252 },
253 )))
254 }
255 SessionConfigResponseChild::SessionUpdateDtTagRangingRoundsRsp(evt) => {
256 Ok(UciResponse::SessionUpdateDtTagRangingRounds(Ok(
257 SessionUpdateDtTagRangingRoundsResponse {
258 status: evt.get_status(),
259 ranging_round_indexes: evt.get_ranging_round_indexes().to_vec(),
260 },
261 )))
262 }
263 SessionConfigResponseChild::SessionSetAppConfigRsp(evt) => {
264 Ok(UciResponse::SessionSetAppConfig(SetAppConfigResponse {
265 status: evt.get_status(),
266 config_status: evt.get_cfg_status().clone(),
267 }))
268 }
269 SessionConfigResponseChild::SessionGetAppConfigRsp(evt) => {
270 Ok(UciResponse::SessionGetAppConfig(
271 status_code_to_result(evt.get_status()).map(|_| {
272 evt.get_tlvs().clone().into_iter().map(|tlv| tlv.into()).collect()
273 }),
274 ))
275 }
276 SessionConfigResponseChild::SessionQueryMaxDataSizeRsp(evt) => {
277 Ok(UciResponse::SessionQueryMaxDataSize(
278 status_code_to_result(evt.get_status()).map(|_| evt.get_max_data_size()),
279 ))
280 }
281 SessionConfigResponseChild::SessionSetHybridControllerConfigRsp(evt) => {
282 Ok(UciResponse::SessionSetHybridControllerConfig(status_code_to_result(
283 evt.get_status(),
284 )))
285 }
286 SessionConfigResponseChild::SessionSetHybridControleeConfigRsp(evt) => {
287 Ok(UciResponse::SessionSetHybridControleeConfig(status_code_to_result(
288 evt.get_status(),
289 )))
290 }
291 SessionConfigResponseChild::SessionDataTransferPhaseConfigRsp(evt) => {
292 Ok(UciResponse::SessionDataTransferPhaseConfig(status_code_to_result(
293 evt.get_status(),
294 )))
295 }
296 _ => Err(Error::Unknown),
297 }
298 }
299 }
300
301 impl TryFrom<uwb_uci_packets::SessionControlResponse> for UciResponse {
302 type Error = Error;
try_from( evt: uwb_uci_packets::SessionControlResponse, ) -> std::result::Result<Self, Self::Error>303 fn try_from(
304 evt: uwb_uci_packets::SessionControlResponse,
305 ) -> std::result::Result<Self, Self::Error> {
306 use uwb_uci_packets::SessionControlResponseChild;
307 match evt.specialize() {
308 SessionControlResponseChild::SessionStartRsp(evt) => {
309 Ok(UciResponse::SessionStart(status_code_to_result(evt.get_status())))
310 }
311 SessionControlResponseChild::SessionStopRsp(evt) => {
312 Ok(UciResponse::SessionStop(status_code_to_result(evt.get_status())))
313 }
314 SessionControlResponseChild::SessionGetRangingCountRsp(evt) => {
315 Ok(UciResponse::SessionGetRangingCount(
316 status_code_to_result(evt.get_status()).map(|_| evt.get_count() as usize),
317 ))
318 }
319 _ => Err(Error::Unknown),
320 }
321 }
322 }
323
324 impl TryFrom<uwb_uci_packets::AndroidResponse> for UciResponse {
325 type Error = Error;
try_from(evt: uwb_uci_packets::AndroidResponse) -> std::result::Result<Self, Self::Error>326 fn try_from(evt: uwb_uci_packets::AndroidResponse) -> std::result::Result<Self, Self::Error> {
327 use uwb_uci_packets::AndroidResponseChild;
328 match evt.specialize() {
329 AndroidResponseChild::AndroidSetCountryCodeRsp(evt) => {
330 Ok(UciResponse::AndroidSetCountryCode(status_code_to_result(evt.get_status())))
331 }
332 AndroidResponseChild::AndroidGetPowerStatsRsp(evt) => {
333 Ok(UciResponse::AndroidGetPowerStats(
334 status_code_to_result(evt.get_stats().status).map(|_| evt.get_stats().clone()),
335 ))
336 }
337 AndroidResponseChild::AndroidSetRadarConfigRsp(evt) => {
338 Ok(UciResponse::AndroidSetRadarConfig(AndroidRadarConfigResponse {
339 status: evt.get_status(),
340 config_status: evt.get_cfg_status().clone(),
341 }))
342 }
343 AndroidResponseChild::AndroidGetRadarConfigRsp(evt) => {
344 Ok(UciResponse::AndroidGetRadarConfig(
345 status_code_to_result(evt.get_status()).map(|_| evt.get_tlvs().clone()),
346 ))
347 }
348 _ => Err(Error::Unknown),
349 }
350 }
351 }
352
raw_response(evt: uwb_uci_packets::UciResponse) -> Result<UciResponse>353 fn raw_response(evt: uwb_uci_packets::UciResponse) -> Result<UciResponse> {
354 let gid: u32 = evt.get_group_id().into();
355 let oid: u32 = evt.get_opcode().into();
356 let packet: UciControlPacket = evt.into();
357 Ok(UciResponse::RawUciCmd(Ok(RawUciMessage { gid, oid, payload: packet.to_raw_payload() })))
358 }
359
360 #[cfg(test)]
361 mod tests {
362 use super::*;
363
364 #[test]
test_uci_response_casting_from_uci_vendor_response_packet()365 fn test_uci_response_casting_from_uci_vendor_response_packet() {
366 let mut uci_vendor_rsp_packet = uwb_uci_packets::UciResponse::try_from(
367 uwb_uci_packets::UciVendor_9_ResponseBuilder {
368 opcode: 0x00,
369 payload: Some(vec![0x0, 0x1, 0x2, 0x3].into()),
370 }
371 .build(),
372 )
373 .unwrap();
374 let uci_fira_major_version = UCIMajorVersion::V1;
375 let mut uci_response = UciResponse::try_from((
376 uci_vendor_rsp_packet.clone(),
377 uci_fira_major_version.clone(),
378 false,
379 ))
380 .unwrap();
381 assert_eq!(
382 uci_response,
383 UciResponse::RawUciCmd(Ok(RawUciMessage {
384 gid: 0x9,
385 oid: 0x0,
386 payload: vec![0x0, 0x1, 0x2, 0x3],
387 }))
388 );
389
390 uci_vendor_rsp_packet = uwb_uci_packets::UciResponse::try_from(
391 uwb_uci_packets::UciVendor_A_ResponseBuilder {
392 opcode: 0x00,
393 payload: Some(vec![0x0, 0x1, 0x2, 0x3].into()),
394 }
395 .build(),
396 )
397 .unwrap();
398 uci_response = UciResponse::try_from((
399 uci_vendor_rsp_packet.clone(),
400 uci_fira_major_version.clone(),
401 false,
402 ))
403 .unwrap();
404 assert_eq!(
405 uci_response,
406 UciResponse::RawUciCmd(Ok(RawUciMessage {
407 gid: 0xA,
408 oid: 0x0,
409 payload: vec![0x0, 0x1, 0x2, 0x3],
410 }))
411 );
412
413 uci_vendor_rsp_packet = uwb_uci_packets::UciResponse::try_from(
414 uwb_uci_packets::UciVendor_B_ResponseBuilder {
415 opcode: 0x00,
416 payload: Some(vec![0x0, 0x1, 0x2, 0x3].into()),
417 }
418 .build(),
419 )
420 .unwrap();
421 uci_response = UciResponse::try_from((
422 uci_vendor_rsp_packet.clone(),
423 uci_fira_major_version.clone(),
424 false,
425 ))
426 .unwrap();
427 assert_eq!(
428 uci_response,
429 UciResponse::RawUciCmd(Ok(RawUciMessage {
430 gid: 0xB,
431 oid: 0x0,
432 payload: vec![0x0, 0x1, 0x2, 0x3],
433 }))
434 );
435
436 uci_vendor_rsp_packet = uwb_uci_packets::UciResponse::try_from(
437 uwb_uci_packets::UciVendor_E_ResponseBuilder {
438 opcode: 0x00,
439 payload: Some(vec![0x0, 0x1, 0x2, 0x3].into()),
440 }
441 .build(),
442 )
443 .unwrap();
444 uci_response = UciResponse::try_from((
445 uci_vendor_rsp_packet.clone(),
446 uci_fira_major_version.clone(),
447 false,
448 ))
449 .unwrap();
450 assert_eq!(
451 uci_response,
452 UciResponse::RawUciCmd(Ok(RawUciMessage {
453 gid: 0xE,
454 oid: 0x0,
455 payload: vec![0x0, 0x1, 0x2, 0x3],
456 }))
457 );
458
459 uci_vendor_rsp_packet = uwb_uci_packets::UciResponse::try_from(
460 uwb_uci_packets::UciVendor_F_ResponseBuilder {
461 opcode: 0x00,
462 payload: Some(vec![0x0, 0x1, 0x2, 0x3].into()),
463 }
464 .build(),
465 )
466 .unwrap();
467 uci_response = UciResponse::try_from((
468 uci_vendor_rsp_packet.clone(),
469 uci_fira_major_version.clone(),
470 false,
471 ))
472 .unwrap();
473 assert_eq!(
474 uci_response,
475 UciResponse::RawUciCmd(Ok(RawUciMessage {
476 gid: 0xF,
477 oid: 0x0,
478 payload: vec![0x0, 0x1, 0x2, 0x3],
479 }))
480 );
481 }
482 }
483