xref: /aosp_15_r20/hardware/interfaces/uwb/aidl/default/src/uwb_chip.rs (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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::fs;
11 use tokio::io::{AsyncReadExt, AsyncWriteExt};
12 use tokio::sync::Mutex;
13 
14 enum ClientState {
15     Closed,
16     Opened {
17         callbacks: Strong<dyn IUwbClientCallback>,
18         _death_recipient: DeathRecipient,
19     },
20 }
21 
22 struct ServiceState {
23     client_state: ClientState,
24     writer: fs::File,
25 }
26 
27 pub struct UwbChip {
28     name: String,
29     _handle: tokio::task::JoinHandle<()>,
30     service_state: Arc<Mutex<ServiceState>>,
31 }
32 
33 /// Configure a file descriptor as raw fd.
makeraw(file: fs::File) -> std::io::Result<fs::File>34 pub fn makeraw(file: fs::File) -> std::io::Result<fs::File> {
35     use nix::sys::termios::*;
36     let mut attrs = tcgetattr(&file)?;
37     cfmakeraw(&mut attrs);
38     tcsetattr(&file, SetArg::TCSANOW, &attrs)?;
39     Ok(file)
40 }
41 
42 impl UwbChip {
new(name: String, path: String) -> Self43     pub async fn new(name: String, path: String) -> Self {
44         // Open the serial file and configure it as raw file
45         // descriptor.
46         let mut reader = fs::OpenOptions::new()
47             .read(true)
48             .write(true)
49             .create(false)
50             .open(&path)
51             .await
52             .and_then(makeraw)
53             .expect("failed to open the serial device");
54         let writer = reader
55             .try_clone()
56             .await
57             .expect("failed to clone serial for writing");
58 
59         // Create the chip
60         let service_state = Arc::new(Mutex::new(ServiceState {
61             writer,
62             client_state: ClientState::Closed,
63         }));
64 
65         // Spawn the task that will run the polling loop.
66         let handle = {
67             let service_state = service_state.clone();
68 
69             tokio::task::spawn(async move {
70                 log::info!("UCI reader task started");
71 
72                 const MESSAGE_TYPE_MASK: u8 = 0b11100000;
73                 const DATA_MESSAGE_TYPE: u8 = 0b000;
74                 const UCI_HEADER_SIZE: usize = 4;
75                 const UCI_BUFFER_SIZE: usize = 1024;
76 
77                 let mut buffer = [0; UCI_BUFFER_SIZE];
78 
79                 loop {
80                     reader
81                         .read_exact(&mut buffer[0..UCI_HEADER_SIZE])
82                         .await
83                         .expect("failed to read uci header bytes");
84                     let common_header = buffer[0];
85                     let mt = (common_header & MESSAGE_TYPE_MASK) >> 5;
86                     let payload_length = if mt == DATA_MESSAGE_TYPE {
87                         u16::from_le_bytes([buffer[2], buffer[3]]) as usize
88                     } else {
89                         buffer[3] as usize
90                     };
91 
92                     let total_packet_length = payload_length + UCI_HEADER_SIZE;
93                     reader
94                         .read_exact(&mut buffer[UCI_HEADER_SIZE..total_packet_length])
95                         .await
96                         .expect("failed to read uci payload bytes");
97 
98                     log::debug!(" <-- {:?}", &buffer[0..total_packet_length]);
99 
100                     let service_state = service_state.lock().await;
101                     if let ClientState::Opened { ref callbacks, .. } = service_state.client_state {
102                         callbacks
103                             .onUciMessage(&buffer[0..total_packet_length])
104                             .unwrap();
105                     }
106                 }
107             })
108         };
109 
110         Self {
111             name,
112             _handle: handle,
113             service_state,
114         }
115     }
116 }
117 impl binder::Interface for UwbChip {}
118 
119 #[async_trait]
120 impl IUwbChipAsyncServer for UwbChip {
getName(&self) -> Result<String>121     async fn getName(&self) -> Result<String> {
122         Ok(self.name.clone())
123     }
124 
open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()>125     async fn open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()> {
126         log::debug!("open");
127 
128         let mut service_state = self.service_state.lock().await;
129 
130         if matches!(service_state.client_state, ClientState::Opened { .. }) {
131             log::error!("the state is already opened");
132             return Err(binder::ExceptionCode::ILLEGAL_STATE.into());
133         }
134 
135         let mut death_recipient = {
136             let service_state = self.service_state.clone();
137             DeathRecipient::new(move || {
138                 log::info!("Uwb service has died");
139                 let mut service_state = service_state.blocking_lock();
140                 service_state.client_state = ClientState::Closed;
141             })
142         };
143 
144         callbacks.as_binder().link_to_death(&mut death_recipient)?;
145         callbacks.onHalEvent(UwbEvent::OPEN_CPLT, UwbStatus::OK)?;
146 
147         service_state.client_state = ClientState::Opened {
148             callbacks: callbacks.clone(),
149             _death_recipient: death_recipient,
150         };
151 
152         Ok(())
153     }
154 
close(&self) -> Result<()>155     async fn close(&self) -> Result<()> {
156         log::debug!("close");
157 
158         let mut service_state = self.service_state.lock().await;
159 
160         if matches!(service_state.client_state, ClientState::Closed) {
161             log::error!("the state is already closed");
162             return Err(binder::ExceptionCode::ILLEGAL_STATE.into());
163         }
164 
165         // Send the command Device Reset to stop all running activities
166         // on the UWBS emulator. This is necessary because the emulator
167         // is otherwise not notified of the power down (the serial stays
168         // open).
169         //
170         // The response to the command will be dropped by the polling loop,
171         // as the callbacks will have been removed then.
172         let uci_core_device_reset_cmd = [0x20, 0x00, 0x00, 0x01, 0x00];
173 
174         service_state
175             .writer
176             .write_all(&uci_core_device_reset_cmd)
177             .await
178             .expect("failed to write UCI Device Reset command");
179 
180         if let ClientState::Opened { ref callbacks, .. } = service_state.client_state {
181             callbacks.onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK)?;
182         }
183 
184         service_state.client_state = ClientState::Closed;
185         Ok(())
186     }
187 
coreInit(&self) -> Result<()>188     async fn coreInit(&self) -> Result<()> {
189         log::debug!("coreInit");
190 
191         let service_state = self.service_state.lock().await;
192 
193         if let ClientState::Opened { ref callbacks, .. } = service_state.client_state {
194             callbacks.onHalEvent(UwbEvent::POST_INIT_CPLT, UwbStatus::OK)?;
195             Ok(())
196         } else {
197             Err(binder::ExceptionCode::ILLEGAL_STATE.into())
198         }
199     }
200 
sessionInit(&self, _id: i32) -> Result<()>201     async fn sessionInit(&self, _id: i32) -> Result<()> {
202         log::debug!("sessionInit");
203 
204         Ok(())
205     }
206 
getSupportedAndroidUciVersion(&self) -> Result<i32>207     async fn getSupportedAndroidUciVersion(&self) -> Result<i32> {
208         log::debug!("getSupportedAndroidUciVersion");
209 
210         Ok(1)
211     }
212 
sendUciMessage(&self, data: &[u8]) -> Result<i32>213     async fn sendUciMessage(&self, data: &[u8]) -> Result<i32> {
214         log::debug!("sendUciMessage");
215 
216         let mut service_state = self.service_state.lock().await;
217 
218         if matches!(service_state.client_state, ClientState::Closed) {
219             log::error!("the state is not opened");
220             return Err(binder::ExceptionCode::ILLEGAL_STATE.into());
221         }
222 
223         log::debug!(" --> {:?}", data);
224         service_state
225             .writer
226             .write_all(data)
227             .await
228             .map(|_| data.len() as i32)
229             .map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into())
230     }
231 }
232