blob: d1c3c67f76810d81ed797c669de201e73eded638 [file] [log] [blame]
Charlie Boutierd572dd02023-04-10 18:14:23 +00001use android_hardware_uwb::aidl::android::hardware::uwb::{
2 IUwbChip::IUwbChipAsyncServer, IUwbClientCallback::IUwbClientCallback, UwbEvent::UwbEvent,
3 UwbStatus::UwbStatus,
4};
5use android_hardware_uwb::binder;
6use async_trait::async_trait;
ziyiw4fec12a2023-09-27 21:00:25 +00007use binder::{DeathRecipient, IBinder, Result, Strong};
Charlie Boutierd572dd02023-04-10 18:14:23 +00008
ziyiw4fec12a2023-09-27 21:00:25 +00009use std::sync::Arc;
10use tokio::io::unix::AsyncFd;
11use tokio::select;
Charlie Boutierd572dd02023-04-10 18:14:23 +000012use tokio::sync::Mutex;
ziyiw4fec12a2023-09-27 21:00:25 +000013use tokio_util::sync::CancellationToken;
Charlie Boutierd572dd02023-04-10 18:14:23 +000014
ziyiw4fec12a2023-09-27 21:00:25 +000015use std::fs::{File, OpenOptions};
16use std::io::{self, Read, Write};
Henri Chataing7e798082023-10-05 16:14:12 +000017use std::os::unix::fs::OpenOptionsExt;
Charlie Boutierd572dd02023-04-10 18:14:23 +000018
ziyiw49aa3352023-12-08 22:40:55 +000019use pdl_runtime::Packet;
20use uwb_uci_packets::{DeviceResetCmdBuilder, ResetConfig, UciControlPacket, UciControlPacketHal};
21
Charlie Boutierd572dd02023-04-10 18:14:23 +000022enum State {
23 Closed,
24 Opened {
25 callbacks: Strong<dyn IUwbClientCallback>,
Henri Chataing7e798082023-10-05 16:14:12 +000026 handle: tokio::task::JoinHandle<()>,
Henri Chataing77971b32023-08-16 16:55:24 +000027 serial: File,
ziyiw4fec12a2023-09-27 21:00:25 +000028 death_recipient: DeathRecipient,
29 token: CancellationToken,
Charlie Boutierd572dd02023-04-10 18:14:23 +000030 },
31}
32
33pub struct UwbChip {
34 name: String,
35 path: String,
ziyiw4fec12a2023-09-27 21:00:25 +000036 state: Arc<Mutex<State>>,
Charlie Boutierd572dd02023-04-10 18:14:23 +000037}
38
39impl UwbChip {
40 pub fn new(name: String, path: String) -> Self {
41 Self {
42 name,
43 path,
ziyiw4fec12a2023-09-27 21:00:25 +000044 state: Arc::new(Mutex::new(State::Closed)),
Charlie Boutierd572dd02023-04-10 18:14:23 +000045 }
46 }
47}
48
ziyiw4fec12a2023-09-27 21:00:25 +000049impl State {
50 /// Terminate the reader task.
Henri Chataing7e798082023-10-05 16:14:12 +000051 async fn close(&mut self) -> Result<()> {
ziyiw49aa3352023-12-08 22:40:55 +000052 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 {
ziyiw4fec12a2023-09-27 21:00:25 +000060 log::info!("waiting for task cancellation");
61 callbacks.as_binder().unlink_to_death(death_recipient)?;
62 token.cancel();
Henri Chataing7e798082023-10-05 16:14:12 +000063 handle.await.unwrap();
ziyiw965dd142023-12-19 21:19:24 +000064 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.to_vec())
75 .map(|written| written as i32)
76 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
77 }
ziyiw49aa3352023-12-08 22:40:55 +000078 consume_device_reset_rsp_and_ntf(
79 &mut serial
80 .try_clone()
81 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?,
82 );
ziyiw4fec12a2023-09-27 21:00:25 +000083 log::info!("task successfully cancelled");
84 callbacks.onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK)?;
85 *self = State::Closed;
86 }
87 Ok(())
88 }
89}
90
ziyiw49aa3352023-12-08 22:40:55 +000091fn 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
Charlie Boutierd572dd02023-04-10 18:14:23 +0000105pub fn makeraw(file: File) -> io::Result<File> {
Andrew Walbran116bf2a2023-12-05 16:17:24 +0000106 // Configure the file descriptor as raw fd.
ziyiw4fec12a2023-09-27 21:00:25 +0000107 use nix::sys::termios::*;
Andrew Walbran116bf2a2023-12-05 16:17:24 +0000108 let mut attrs = tcgetattr(&file)?;
ziyiw4fec12a2023-09-27 21:00:25 +0000109 cfmakeraw(&mut attrs);
Andrew Walbran116bf2a2023-12-05 16:17:24 +0000110 tcsetattr(&file, SetArg::TCSANOW, &attrs)?;
Charlie Boutierd572dd02023-04-10 18:14:23 +0000111
Charlie Boutierd572dd02023-04-10 18:14:23 +0000112 Ok(file)
113}
114
ziyiw4fec12a2023-09-27 21:00:25 +0000115/// 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.
118fn 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
Charlie Boutierd572dd02023-04-10 18:14:23 +0000130impl binder::Interface for UwbChip {}
131
132#[async_trait]
133impl IUwbChipAsyncServer for UwbChip {
134 async fn getName(&self) -> Result<String> {
135 Ok(self.name.clone())
136 }
137
138 async fn open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()> {
139 log::debug!("open: {:?}", &self.path);
140
ziyiw4fec12a2023-09-27 21:00:25 +0000141 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
Henri Chataing77971b32023-08-16 16:55:24 +0000148 let serial = OpenOptions::new()
149 .read(true)
150 .write(true)
151 .create(false)
Henri Chataing7e798082023-10-05 16:14:12 +0000152 .custom_flags(libc::O_NONBLOCK)
Henri Chataing77971b32023-08-16 16:55:24 +0000153 .open(&self.path)
Charlie Boutierd572dd02023-04-10 18:14:23 +0000154 .and_then(makeraw)
155 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
156
ziyiw4fec12a2023-09-27 21:00:25 +0000157 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");
Henri Chataing7e798082023-10-05 16:14:12 +0000161 if let State::Opened { ref mut token, .. } = *state {
162 token.cancel();
163 *state = State::Closed;
164 }
ziyiw4fec12a2023-09-27 21:00:25 +0000165 });
Charlie Boutierd572dd02023-04-10 18:14:23 +0000166
ziyiw4fec12a2023-09-27 21:00:25 +0000167 callbacks.as_binder().link_to_death(&mut death_recipient)?;
Charlie Boutierd572dd02023-04-10 18:14:23 +0000168
ziyiw4fec12a2023-09-27 21:00:25 +0000169 let token = CancellationToken::new();
170 let cloned_token = token.clone();
Charlie Boutierd572dd02023-04-10 18:14:23 +0000171
ziyiw4fec12a2023-09-27 21:00:25 +0000172 let client_callbacks = callbacks.clone();
Charlie Boutierd572dd02023-04-10 18:14:23 +0000173
ziyiw4fec12a2023-09-27 21:00:25 +0000174 let reader = serial
175 .try_clone()
176 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
Charlie Boutierd572dd02023-04-10 18:14:23 +0000177
ziyiw4fec12a2023-09-27 21:00:25 +0000178 let join_handle = tokio::task::spawn(async move {
Henri Chataing7e798082023-10-05 16:14:12 +0000179 log::info!("UCI reader task started");
ziyiw4fec12a2023-09-27 21:00:25 +0000180 let mut reader = AsyncFd::new(reader).unwrap();
Charlie Boutierd572dd02023-04-10 18:14:23 +0000181
ziyiw4fec12a2023-09-27 21:00:25 +0000182 loop {
183 const UWB_HEADER_SIZE: usize = 4;
184 let mut buffer = vec![0; UWB_HEADER_SIZE];
Charlie Boutierd572dd02023-04-10 18:14:23 +0000185
ziyiw4fec12a2023-09-27 21:00:25 +0000186 // The only time where the task can be safely
187 // cancelled is when no packet bytes have been read.
188 //
189 // - read_exact() cannot be used here since it is not
190 // cancellation safe.
191 // - read() cannot be used because it cannot be cancelled:
192 // the syscall is executed blocking on the threadpool
193 // and completes after termination of the task when
194 // the pipe receives more data.
195 let read_len = loop {
196 // On some platforms, the readiness detecting mechanism
197 // relies on edge-triggered notifications. This means that
198 // the OS will only notify Tokio when the file descriptor
199 // transitions from not-ready to ready. For this to work
200 // you should first try to read or write and only poll for
Henri Chataing7e798082023-10-05 16:14:12 +0000201 // readiness if that fails with an error of
ziyiw4fec12a2023-09-27 21:00:25 +0000202 // std::io::ErrorKind::WouldBlock.
203 match reader.get_mut().read(&mut buffer) {
204 Ok(0) => {
205 log::error!("file unexpectedly closed");
206 return;
207 }
208 Ok(read_len) => break read_len,
209 Err(err) if err.kind() == io::ErrorKind::WouldBlock => (),
210 Err(_) => panic!("unexpected read failure"),
211 }
Charlie Boutierd572dd02023-04-10 18:14:23 +0000212
ziyiw4fec12a2023-09-27 21:00:25 +0000213 let mut guard = select! {
214 _ = cloned_token.cancelled() => {
Henri Chataing7e798082023-10-05 16:14:12 +0000215 log::info!("task is cancelled!");
ziyiw4fec12a2023-09-27 21:00:25 +0000216 return;
217 },
218 result = reader.readable() => result.unwrap()
219 };
Charlie Boutierd572dd02023-04-10 18:14:23 +0000220
ziyiw4fec12a2023-09-27 21:00:25 +0000221 guard.clear_ready();
222 };
Charlie Boutierd572dd02023-04-10 18:14:23 +0000223
ziyiw4fec12a2023-09-27 21:00:25 +0000224 // Read the remaining header bytes, if truncated.
225 read_exact(reader.get_mut(), &mut buffer[read_len..]).unwrap();
226
227 let length = buffer[3] as usize + UWB_HEADER_SIZE;
228 buffer.resize(length, 0);
229
230 // Read the payload bytes.
231 read_exact(reader.get_mut(), &mut buffer[UWB_HEADER_SIZE..]).unwrap();
232
233 client_callbacks.onUciMessage(&buffer).unwrap();
234 }
235 });
236
237 callbacks.onHalEvent(UwbEvent::OPEN_CPLT, UwbStatus::OK)?;
238
239 *state = State::Opened {
240 callbacks: callbacks.clone(),
Henri Chataing7e798082023-10-05 16:14:12 +0000241 handle: join_handle,
ziyiw4fec12a2023-09-27 21:00:25 +0000242 serial,
243 death_recipient,
244 token,
245 };
246
247 Ok(())
Charlie Boutierd572dd02023-04-10 18:14:23 +0000248 }
249
250 async fn close(&self) -> Result<()> {
251 log::debug!("close");
252
253 let mut state = self.state.lock().await;
254
ziyiw965dd142023-12-19 21:19:24 +0000255 if let State::Opened { .. } = *state {
Henri Chataing7e798082023-10-05 16:14:12 +0000256 state.close().await
Charlie Boutierd572dd02023-04-10 18:14:23 +0000257 } else {
258 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
259 }
260 }
261
262 async fn coreInit(&self) -> Result<()> {
263 log::debug!("coreInit");
264
265 if let State::Opened { ref callbacks, .. } = *self.state.lock().await {
266 callbacks.onHalEvent(UwbEvent::POST_INIT_CPLT, UwbStatus::OK)?;
267 Ok(())
268 } else {
269 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
270 }
271 }
272
273 async fn sessionInit(&self, _id: i32) -> Result<()> {
274 log::debug!("sessionInit");
275
276 Ok(())
277 }
278
279 async fn getSupportedAndroidUciVersion(&self) -> Result<i32> {
280 Ok(1)
281 }
282
283 async fn sendUciMessage(&self, data: &[u8]) -> Result<i32> {
284 log::debug!("sendUciMessage");
285
Henri Chataing77971b32023-08-16 16:55:24 +0000286 if let State::Opened { ref mut serial, .. } = &mut *self.state.lock().await {
287 serial
288 .write(data)
Henri Chataing77971b32023-08-16 16:55:24 +0000289 .map(|written| written as i32)
Charlie Boutierd572dd02023-04-10 18:14:23 +0000290 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into())
291 } else {
292 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
293 }
294 }
295}