• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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