blob: 9587efba5dd27f1e14ea179a48657b6c20d686c7 [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;
7use binder::{Result, Strong};
8
Henri Chataing77971b32023-08-16 16:55:24 +00009use tokio::fs::{File, OpenOptions};
10use tokio::io::{AsyncReadExt, AsyncWriteExt};
Charlie Boutierd572dd02023-04-10 18:14:23 +000011use tokio::sync::Mutex;
12
13use std::os::fd::AsRawFd;
14
15use std::io;
16
17use nix::sys::termios;
18
19enum State {
20 Closed,
21 Opened {
22 callbacks: Strong<dyn IUwbClientCallback>,
23 #[allow(dead_code)]
24 tasks: tokio::task::JoinSet<()>,
Henri Chataing77971b32023-08-16 16:55:24 +000025 serial: File,
Charlie Boutierd572dd02023-04-10 18:14:23 +000026 },
27}
28
29pub struct UwbChip {
30 name: String,
31 path: String,
32 state: Mutex<State>,
33}
34
35impl UwbChip {
36 pub fn new(name: String, path: String) -> Self {
37 Self {
38 name,
39 path,
40 state: Mutex::new(State::Closed),
41 }
42 }
43}
44
45pub fn makeraw(file: File) -> io::Result<File> {
46 let fd = file.as_raw_fd();
47
48 let mut attrs = termios::tcgetattr(fd)?;
49
50 termios::cfmakeraw(&mut attrs);
51
52 termios::tcsetattr(fd, termios::SetArg::TCSANOW, &attrs)?;
53
54 Ok(file)
55}
56
57impl binder::Interface for UwbChip {}
58
59#[async_trait]
60impl IUwbChipAsyncServer for UwbChip {
61 async fn getName(&self) -> Result<String> {
62 Ok(self.name.clone())
63 }
64
65 async fn open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()> {
66 log::debug!("open: {:?}", &self.path);
67
Henri Chataing77971b32023-08-16 16:55:24 +000068 let serial = OpenOptions::new()
69 .read(true)
70 .write(true)
71 .create(false)
72 .open(&self.path)
Charlie Boutierd572dd02023-04-10 18:14:23 +000073 .await
74 .and_then(makeraw)
75 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
76
Charlie Boutierd572dd02023-04-10 18:14:23 +000077 let mut state = self.state.lock().await;
78
79 if let State::Closed = *state {
80 let client_callbacks = callbacks.clone();
81
82 let mut tasks = tokio::task::JoinSet::new();
Henri Chataing77971b32023-08-16 16:55:24 +000083 let mut reader = serial
84 .try_clone()
85 .await
86 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
Charlie Boutierd572dd02023-04-10 18:14:23 +000087
88 tasks.spawn(async move {
89 loop {
90 const UWB_HEADER_SIZE: usize = 4;
91
92 let mut buffer = vec![0; UWB_HEADER_SIZE];
Henri Chataing77971b32023-08-16 16:55:24 +000093 reader
Charlie Boutier3561c842023-05-02 00:06:28 +000094 .read_exact(&mut buffer[0..UWB_HEADER_SIZE])
Charlie Boutierd572dd02023-04-10 18:14:23 +000095 .await
96 .unwrap();
97
98 let length = buffer[3] as usize + UWB_HEADER_SIZE;
99
100 buffer.resize(length, 0);
Henri Chataing77971b32023-08-16 16:55:24 +0000101 reader
Charlie Boutier3561c842023-05-02 00:06:28 +0000102 .read_exact(&mut buffer[UWB_HEADER_SIZE..length])
Charlie Boutierd572dd02023-04-10 18:14:23 +0000103 .await
104 .unwrap();
105
106 client_callbacks.onUciMessage(&buffer[..]).unwrap();
107 }
108 });
109
110 callbacks.onHalEvent(UwbEvent::OPEN_CPLT, UwbStatus::OK)?;
111
112 *state = State::Opened {
113 callbacks: callbacks.clone(),
114 tasks,
Henri Chataing77971b32023-08-16 16:55:24 +0000115 serial,
Charlie Boutierd572dd02023-04-10 18:14:23 +0000116 };
117
118 Ok(())
119 } else {
120 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
121 }
122 }
123
124 async fn close(&self) -> Result<()> {
125 log::debug!("close");
126
127 let mut state = self.state.lock().await;
128
129 if let State::Opened { ref callbacks, .. } = *state {
130 callbacks.onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK)?;
131 *state = State::Closed;
132 Ok(())
133 } else {
134 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
135 }
136 }
137
138 async fn coreInit(&self) -> Result<()> {
139 log::debug!("coreInit");
140
141 if let State::Opened { ref callbacks, .. } = *self.state.lock().await {
142 callbacks.onHalEvent(UwbEvent::POST_INIT_CPLT, UwbStatus::OK)?;
143 Ok(())
144 } else {
145 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
146 }
147 }
148
149 async fn sessionInit(&self, _id: i32) -> Result<()> {
150 log::debug!("sessionInit");
151
152 Ok(())
153 }
154
155 async fn getSupportedAndroidUciVersion(&self) -> Result<i32> {
156 Ok(1)
157 }
158
159 async fn sendUciMessage(&self, data: &[u8]) -> Result<i32> {
160 log::debug!("sendUciMessage");
161
Henri Chataing77971b32023-08-16 16:55:24 +0000162 if let State::Opened { ref mut serial, .. } = &mut *self.state.lock().await {
163 serial
164 .write(data)
Charlie Boutierd572dd02023-04-10 18:14:23 +0000165 .await
Henri Chataing77971b32023-08-16 16:55:24 +0000166 .map(|written| written as i32)
Charlie Boutierd572dd02023-04-10 18:14:23 +0000167 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into())
168 } else {
169 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
170 }
171 }
172}