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