• 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 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