blob: 7c2c30056dc02bc1ed0357a725be56d9663c2beb [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
9use tokio::fs::File;
10use tokio::io::{AsyncReadExt, AsyncWriteExt};
11use 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<()>,
25 write: File,
26 },
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
68 let serial = File::open(&self.path)
69 .await
70 .and_then(makeraw)
71 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
72
73 let mut read = serial
74 .try_clone()
75 .await
76 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
77 let write = serial;
78
79 let mut state = self.state.lock().await;
80
81 if let State::Closed = *state {
82 let client_callbacks = callbacks.clone();
83
84 let mut tasks = tokio::task::JoinSet::new();
85
86 tasks.spawn(async move {
87 loop {
88 const UWB_HEADER_SIZE: usize = 4;
89
90 let mut buffer = vec![0; UWB_HEADER_SIZE];
91 read.read_exact(&mut buffer[0..UWB_HEADER_SIZE])
92 .await
93 .unwrap();
94
95 let length = buffer[3] as usize + UWB_HEADER_SIZE;
96
97 buffer.resize(length, 0);
98 read.read_exact(&mut buffer[UWB_HEADER_SIZE..length])
99 .await
100 .unwrap();
101
102 client_callbacks.onUciMessage(&buffer[..]).unwrap();
103 }
104 });
105
106 callbacks.onHalEvent(UwbEvent::OPEN_CPLT, UwbStatus::OK)?;
107
108 *state = State::Opened {
109 callbacks: callbacks.clone(),
110 tasks,
111 write,
112 };
113
114 Ok(())
115 } else {
116 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
117 }
118 }
119
120 async fn close(&self) -> Result<()> {
121 log::debug!("close");
122
123 let mut state = self.state.lock().await;
124
125 if let State::Opened { ref callbacks, .. } = *state {
126 callbacks.onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK)?;
127 *state = State::Closed;
128 Ok(())
129 } else {
130 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
131 }
132 }
133
134 async fn coreInit(&self) -> Result<()> {
135 log::debug!("coreInit");
136
137 if let State::Opened { ref callbacks, .. } = *self.state.lock().await {
138 callbacks.onHalEvent(UwbEvent::POST_INIT_CPLT, UwbStatus::OK)?;
139 Ok(())
140 } else {
141 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
142 }
143 }
144
145 async fn sessionInit(&self, _id: i32) -> Result<()> {
146 log::debug!("sessionInit");
147
148 Ok(())
149 }
150
151 async fn getSupportedAndroidUciVersion(&self) -> Result<i32> {
152 Ok(1)
153 }
154
155 async fn sendUciMessage(&self, data: &[u8]) -> Result<i32> {
156 log::debug!("sendUciMessage");
157
158 if let State::Opened { write, .. } = &mut *self.state.lock().await {
159 write
160 .write(data)
161 .await
162 .map(|written| written as i32)
163 .map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into())
164 } else {
165 Err(binder::ExceptionCode::ILLEGAL_STATE.into())
166 }
167 }
168}