1 use android_hardware_uwb::aidl::android::hardware::uwb::{
2 IUwbChip::IUwbChipAsyncServer, IUwbClientCallback::IUwbClientCallback, UwbEvent::UwbEvent,
3 UwbStatus::UwbStatus,
4 };
5 use android_hardware_uwb::binder;
6 use async_trait::async_trait;
7 use binder::{DeathRecipient, IBinder, Result, Strong};
8
9 use std::sync::Arc;
10 use tokio::io::unix::AsyncFd;
11 use tokio::select;
12 use tokio::sync::Mutex;
13 use tokio_util::sync::CancellationToken;
14
15 use std::fs::{File, OpenOptions};
16 use std::io::{self, Read, Write};
17 use std::os::unix::fs::OpenOptionsExt;
18
19 use pdl_runtime::Packet;
20 use uwb_uci_packets::{DeviceResetCmdBuilder, ResetConfig, UciControlPacket, UciControlPacketHal};
21
22 enum State {
23 Closed,
24 Opened {
25 callbacks: Strong<dyn IUwbClientCallback>,
26 handle: tokio::task::JoinHandle<()>,
27 serial: File,
28 death_recipient: DeathRecipient,
29 token: CancellationToken,
30 },
31 }
32
33 pub struct UwbChip {
34 name: String,
35 path: String,
36 state: Arc<Mutex<State>>,
37 }
38
39 impl UwbChip {
new(name: String, path: String) -> Self40 pub fn new(name: String, path: String) -> Self {
41 Self {
42 name,
43 path,
44 state: Arc::new(Mutex::new(State::Closed)),
45 }
46 }
47 }
48
49 impl State {
50 /// Terminate the reader task.
close(&mut self) -> Result<()>51 async fn close(&mut self) -> Result<()> {
52 if let State::Opened {
53 ref mut token,
54 ref callbacks,
55 ref mut death_recipient,
56 ref mut handle,
57 ref mut serial,
58 } = *self
59 {
60 log::info!("waiting for task cancellation");
61 callbacks.as_binder().unlink_to_death(death_recipient)?;
62 token.cancel();
63 handle.await.unwrap();
64 let packet: UciControlPacket = DeviceResetCmdBuilder {
65 reset_config: ResetConfig::UwbsReset,
66 }
67 .build()
68 .into();
69 // DeviceResetCmd need to be send to reset the device to stop all running
70 // activities on UWBS.
71 let packet_vec: Vec<UciControlPacketHal> = packet.into();
72 for hal_packet in packet_vec.into_iter() {
73 serial
74 .write(&hal_packet.encode_to_vec().unwrap())
75 .map(|written| written as i32)
76 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
77 }
78 consume_device_reset_rsp_and_ntf(
79 &mut serial
80 .try_clone()
81 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?,
82 );
83 log::info!("task successfully cancelled");
84 callbacks.onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK)?;
85 *self = State::Closed;
86 }
87 Ok(())
88 }
89 }
90
consume_device_reset_rsp_and_ntf(reader: &mut File)91 fn consume_device_reset_rsp_and_ntf(reader: &mut File) {
92 // Poll the DeviceResetRsp and DeviceStatusNtf before hal is closed to prevent
93 // the host from getting response and notifications from a 'powered down' UWBS.
94 // Do nothing when these packets are received.
95 const DEVICE_RESET_RSP: [u8; 5] = [64, 0, 0, 1, 0];
96 const DEVICE_STATUS_NTF: [u8; 5] = [96, 1, 0, 1, 1];
97 let mut buffer = vec![0; DEVICE_RESET_RSP.len() + DEVICE_STATUS_NTF.len()];
98 read_exact(reader, &mut buffer).unwrap();
99
100 // Make sure received packets are the expected ones.
101 assert_eq!(&buffer[0..DEVICE_RESET_RSP.len()], &DEVICE_RESET_RSP);
102 assert_eq!(&buffer[DEVICE_RESET_RSP.len()..], &DEVICE_STATUS_NTF);
103 }
104
makeraw(file: File) -> io::Result<File>105 pub fn makeraw(file: File) -> io::Result<File> {
106 // Configure the file descriptor as raw fd.
107 use nix::sys::termios::*;
108 let mut attrs = tcgetattr(&file)?;
109 cfmakeraw(&mut attrs);
110 tcsetattr(&file, SetArg::TCSANOW, &attrs)?;
111
112 Ok(file)
113 }
114
115 /// Wrapper around Read::read to handle EWOULDBLOCK.
116 /// /!\ will actively wait for more data, make sure to call
117 /// this method only when data is immediately expected.
read_exact(file: &mut File, mut buf: &mut [u8]) -> io::Result<()>118 fn read_exact(file: &mut File, mut buf: &mut [u8]) -> io::Result<()> {
119 while buf.len() > 0 {
120 match file.read(buf) {
121 Ok(0) => panic!("unexpectedly reached end of file"),
122 Ok(read_len) => buf = &mut buf[read_len..],
123 Err(err) if err.kind() == io::ErrorKind::WouldBlock => continue,
124 Err(err) => return Err(err),
125 }
126 }
127 Ok(())
128 }
129
130 impl binder::Interface for UwbChip {}
131
132 #[async_trait]
133 impl IUwbChipAsyncServer for UwbChip {
getName(&self) -> Result<String>134 async fn getName(&self) -> Result<String> {
135 Ok(self.name.clone())
136 }
137
open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()>138 async fn open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()> {
139 log::debug!("open: {:?}", &self.path);
140
141 let mut state = self.state.lock().await;
142
143 if matches!(*state, State::Opened { .. }) {
144 log::error!("the state is already opened");
145 return Err(binder::ExceptionCode::ILLEGAL_STATE.into());
146 }
147
148 let serial = OpenOptions::new()
149 .read(true)
150 .write(true)
151 .create(false)
152 .custom_flags(libc::O_NONBLOCK)
153 .open(&self.path)
154 .and_then(makeraw)
155 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
156
157 let state_death_recipient = self.state.clone();
158 let mut death_recipient = DeathRecipient::new(move || {
159 let mut state = state_death_recipient.blocking_lock();
160 log::info!("Uwb service has died");
161 if let State::Opened { ref mut token, .. } = *state {
162 token.cancel();
163 *state = State::Closed;
164 }
165 });
166
167 callbacks.as_binder().link_to_death(&mut death_recipient)?;
168
169 let token = CancellationToken::new();
170 let cloned_token = token.clone();
171
172 let client_callbacks = callbacks.clone();
173
174 let reader = serial
175 .try_clone()
176 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
177
178 let join_handle = tokio::task::spawn(async move {
179 log::info!("UCI reader task started");
180 let mut reader = AsyncFd::new(reader).unwrap();
181
182 loop {
183 const MESSAGE_TYPE_MASK: u8 = 0b11100000;
184 const DATA_MESSAGE_TYPE: u8 = 0b000;
185 const UWB_HEADER_SIZE: usize = 4;
186 let mut buffer = vec![0; UWB_HEADER_SIZE];
187
188 // The only time where the task can be safely
189 // cancelled is when no packet bytes have been read.
190 //
191 // - read_exact() cannot be used here since it is not
192 // cancellation safe.
193 // - read() cannot be used because it cannot be cancelled:
194 // the syscall is executed blocking on the threadpool
195 // and completes after termination of the task when
196 // the pipe receives more data.
197 let read_len = loop {
198 // On some platforms, the readiness detecting mechanism
199 // relies on edge-triggered notifications. This means that
200 // the OS will only notify Tokio when the file descriptor
201 // transitions from not-ready to ready. For this to work
202 // you should first try to read or write and only poll for
203 // readiness if that fails with an error of
204 // std::io::ErrorKind::WouldBlock.
205 match reader.get_mut().read(&mut buffer) {
206 Ok(0) => {
207 log::error!("file unexpectedly closed");
208 return;
209 }
210 Ok(read_len) => break read_len,
211 Err(err) if err.kind() == io::ErrorKind::WouldBlock => (),
212 Err(_) => panic!("unexpected read failure"),
213 }
214
215 let mut guard = select! {
216 _ = cloned_token.cancelled() => {
217 log::info!("task is cancelled!");
218 return;
219 },
220 result = reader.readable() => result.unwrap()
221 };
222
223 guard.clear_ready();
224 };
225
226 // Read the remaining header bytes, if truncated.
227 read_exact(reader.get_mut(), &mut buffer[read_len..]).unwrap();
228
229 let common_header = buffer[0];
230 let mt = (common_header & MESSAGE_TYPE_MASK) >> 5;
231 let payload_length = if mt == DATA_MESSAGE_TYPE {
232 let payload_length_fields: [u8; 2] = buffer[2..=3].try_into().unwrap();
233 u16::from_le_bytes(payload_length_fields) as usize
234 } else {
235 buffer[3] as usize
236 };
237
238 let length = payload_length + UWB_HEADER_SIZE;
239 buffer.resize(length, 0);
240
241 // Read the payload bytes.
242 read_exact(reader.get_mut(), &mut buffer[UWB_HEADER_SIZE..]).unwrap();
243
244 log::debug!(" <-- {:?}", buffer);
245 client_callbacks.onUciMessage(&buffer).unwrap();
246 }
247 });
248
249 callbacks.onHalEvent(UwbEvent::OPEN_CPLT, UwbStatus::OK)?;
250
251 *state = State::Opened {
252 callbacks: callbacks.clone(),
253 handle: join_handle,
254 serial,
255 death_recipient,
256 token,
257 };
258
259 Ok(())
260 }
261
close(&self) -> Result<()>262 async fn close(&self) -> Result<()> {
263 log::debug!("close");
264
265 let mut state = self.state.lock().await;
266
267 if let State::Opened { .. } = *state {
268 state.close().await
269 } else {
270 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
271 }
272 }
273
coreInit(&self) -> Result<()>274 async fn coreInit(&self) -> Result<()> {
275 log::debug!("coreInit");
276
277 if let State::Opened { ref callbacks, .. } = *self.state.lock().await {
278 callbacks.onHalEvent(UwbEvent::POST_INIT_CPLT, UwbStatus::OK)?;
279 Ok(())
280 } else {
281 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
282 }
283 }
284
sessionInit(&self, _id: i32) -> Result<()>285 async fn sessionInit(&self, _id: i32) -> Result<()> {
286 log::debug!("sessionInit");
287
288 Ok(())
289 }
290
getSupportedAndroidUciVersion(&self) -> Result<i32>291 async fn getSupportedAndroidUciVersion(&self) -> Result<i32> {
292 Ok(1)
293 }
294
sendUciMessage(&self, data: &[u8]) -> Result<i32>295 async fn sendUciMessage(&self, data: &[u8]) -> Result<i32> {
296 log::debug!("sendUciMessage");
297
298 if let State::Opened { ref mut serial, .. } = &mut *self.state.lock().await {
299 log::debug!(" --> {:?}", data);
300 let result = serial
301 .write_all(data)
302 .map(|_| data.len() as i32)
303 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into());
304 log::debug!(" status: {:?}", result);
305 result
306 } else {
307 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
308 }
309 }
310 }
311