1 // Copyright 2024, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! Bluetooth HCI Service implementation.
16
17 use android_hardware_bluetooth::aidl::android::hardware::bluetooth::{
18 IBluetoothHci::IBluetoothHci, IBluetoothHciCallbacks::IBluetoothHciCallbacks, Status::Status,
19 };
20
21 use binder::{DeathRecipient, IBinder, Interface, Strong};
22 use log::{error, info, trace, warn};
23 use std::fs;
24 use std::io::{Read, Write};
25 use std::os::fd::AsRawFd;
26 use std::os::unix::fs::OpenOptionsExt;
27 use std::sync::mpsc;
28 use std::sync::{Arc, Mutex};
29
30 #[derive(Clone, Copy, Debug)]
31 enum Idc {
32 Command = 1,
33 AclData = 2,
34 ScoData = 3,
35 Event = 4,
36 IsoData = 5,
37 }
38
39 impl Idc {
40 const ACL_DATA: u8 = Idc::AclData as u8;
41 const SCO_DATA: u8 = Idc::ScoData as u8;
42 const EVENT: u8 = Idc::Event as u8;
43 const ISO_DATA: u8 = Idc::IsoData as u8;
44 }
45
46 enum ClientState {
47 Closed,
48 Opened {
49 initialized: bool,
50 callbacks: Strong<dyn IBluetoothHciCallbacks>,
51 _death_recipient: DeathRecipient,
52 },
53 }
54
55 struct ServiceState {
56 writer: fs::File,
57 client_state: ClientState,
58 }
59
60 pub struct BluetoothHci {
61 _handle: std::thread::JoinHandle<()>,
62 service_state: Arc<Mutex<ServiceState>>,
63 }
64
65 /// Configure a file descriptor as raw fd.
make_raw(file: fs::File) -> std::io::Result<fs::File>66 fn make_raw(file: fs::File) -> std::io::Result<fs::File> {
67 use nix::sys::termios::*;
68 let mut attrs = tcgetattr(&file)?;
69 cfmakeraw(&mut attrs);
70 tcsetattr(&file, SetArg::TCSANOW, &attrs)?;
71 Ok(file)
72 }
73
74 /// Clear all data that might be left in the virtio-console
75 /// device from a previous session.
clear(mut file: fs::File) -> std::io::Result<fs::File>76 fn clear(mut file: fs::File) -> std::io::Result<fs::File> {
77 use nix::fcntl::*;
78 let mut flags = OFlag::from_bits_truncate(fcntl(file.as_raw_fd(), FcntlArg::F_GETFL)?);
79
80 // Make the input file nonblocking when checking if any data
81 // is available to read().
82 flags.insert(OFlag::O_NONBLOCK);
83 fcntl(file.as_raw_fd(), FcntlArg::F_SETFL(flags))?;
84
85 // Drain bytes present in the file.
86 let mut data = [0; 4096];
87 loop {
88 match file.read(&mut data) {
89 // The return value 0 indicates that the file was
90 // closed remotely.
91 Ok(0) => panic!("failed to clear the serial device"),
92 Ok(size) if size == data.len() => (),
93 Ok(_) => break,
94 Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => break,
95 Err(err) => return Err(err),
96 }
97 }
98
99 // Restore the input file to blocking.
100 flags.remove(OFlag::O_NONBLOCK);
101 fcntl(file.as_raw_fd(), FcntlArg::F_SETFL(flags))?;
102
103 Ok(file)
104 }
105
106 impl BluetoothHci {
new(path: &str) -> Self107 pub fn new(path: &str) -> Self {
108 // Open the serial file and configure it as raw file
109 // descriptor.
110 let mut reader = fs::OpenOptions::new()
111 .read(true)
112 .write(true)
113 .create(false)
114 .open(path)
115 .and_then(make_raw)
116 .and_then(clear)
117 .expect("failed to open the serial device");
118 let writer = reader.try_clone().expect("failed to clone serial for writing");
119
120 // Create the chip
121 let service_state =
122 Arc::new(Mutex::new(ServiceState { writer, client_state: ClientState::Closed }));
123
124 // Spawn the thread that will run the polling loop.
125 let handle = {
126 let service_state = service_state.clone();
127 std::thread::spawn(move || loop {
128 let mut data = [0; 4096];
129
130 // Read the packet idc.
131 reader.read_exact(&mut data[0..1]).unwrap();
132 let idc = data[0];
133
134 // Determine the header size.
135 let header_size = 1 + match idc {
136 Idc::ACL_DATA => 4,
137 Idc::SCO_DATA => 3,
138 Idc::ISO_DATA => 4,
139 Idc::EVENT => 2,
140 _ => panic!("received invalid IDC bytes 0x{:02x}", idc),
141 };
142
143 // Read the packet header bytes.
144 reader.read_exact(&mut data[1..header_size]).unwrap();
145
146 // Determine the payload size.
147 let packet_size = header_size
148 + match idc {
149 Idc::ACL_DATA => u16::from_le_bytes([data[3], data[4]]) as usize,
150 Idc::SCO_DATA => data[3] as usize,
151 Idc::ISO_DATA => (u16::from_le_bytes([data[3], data[4]]) & 0x3fff) as usize,
152 Idc::EVENT => data[2] as usize,
153 _ => unreachable!(),
154 };
155
156 // Read the packet payload bytes.
157 reader.read_exact(&mut data[header_size..packet_size]).unwrap();
158
159 trace!("read packet: {:?}", &data[..packet_size]);
160
161 // Forward the packet to the host stack.
162 {
163 let mut service_state = service_state.lock().unwrap();
164 match service_state.client_state {
165 ClientState::Opened { ref callbacks, ref mut initialized, .. }
166 if !*initialized =>
167 {
168 // While in initialization is pending, all packets are ignored except for the
169 // HCI Reset Complete event.
170 if matches!(
171 &data[0..packet_size],
172 [Idc::EVENT, 0x0e, 0x04, 0x01, 0x03, 0x0c, 0x00]
173 ) {
174 // The initialization of the controller is now complete,
175 // report the status to the Host stack.
176 callbacks.initializationComplete(Status::SUCCESS).unwrap();
177 *initialized = true;
178 }
179 }
180 ClientState::Opened { ref callbacks, .. } => match idc {
181 Idc::ACL_DATA => callbacks.aclDataReceived(&data[1..packet_size]),
182 Idc::SCO_DATA => callbacks.scoDataReceived(&data[1..packet_size]),
183 Idc::ISO_DATA => callbacks.isoDataReceived(&data[1..packet_size]),
184 Idc::EVENT => callbacks.hciEventReceived(&data[1..packet_size]),
185 _ => unreachable!(),
186 }
187 .expect("failed to send HCI packet to host"),
188 ClientState::Closed => (),
189 }
190 }
191 })
192 };
193
194 BluetoothHci { _handle: handle, service_state }
195 }
196
send(&self, idc: Idc, data: &[u8]) -> binder::Result<()>197 fn send(&self, idc: Idc, data: &[u8]) -> binder::Result<()> {
198 let mut service_state = self.service_state.lock().unwrap();
199
200 if !matches!(service_state.client_state, ClientState::Opened { .. }) {
201 error!("IBluetoothHci::sendXX: not initialized");
202 return Err(binder::ExceptionCode::ILLEGAL_STATE.into());
203 }
204
205 service_state.writer.write_all(&[idc as u8]).unwrap();
206 service_state.writer.write_all(data).unwrap();
207
208 Ok(())
209 }
210 }
211
212 impl Interface for BluetoothHci {}
213
214 impl IBluetoothHci for BluetoothHci {
initialize(&self, callbacks: &Strong<dyn IBluetoothHciCallbacks>) -> binder::Result<()>215 fn initialize(&self, callbacks: &Strong<dyn IBluetoothHciCallbacks>) -> binder::Result<()> {
216 info!("IBluetoothHci::initialize");
217
218 let mut service_state = self.service_state.lock().unwrap();
219
220 if matches!(service_state.client_state, ClientState::Opened { .. }) {
221 error!("IBluetoothHci::initialize: already initialized");
222 callbacks.initializationComplete(Status::ALREADY_INITIALIZED)?;
223 return Ok(());
224 }
225
226 let mut death_recipient = {
227 let service_state = self.service_state.clone();
228 DeathRecipient::new(move || {
229 warn!("IBluetoothHci service has died");
230 let mut service_state = service_state.lock().unwrap();
231 service_state.client_state = ClientState::Closed;
232 })
233 };
234
235 callbacks.as_binder().link_to_death(&mut death_recipient)?;
236
237 service_state.client_state = ClientState::Opened {
238 initialized: false,
239 callbacks: callbacks.clone(),
240 _death_recipient: death_recipient,
241 };
242
243 // In order to emulate hardware reset of the controller,
244 // the HCI Reset command is sent from the HAL directly to clear
245 // all controller state.
246 // IBluetoothHciCallback.initializationComplete will be invoked
247 // the HCI Reset complete event is received.
248 service_state.writer.write_all(&[0x01, 0x03, 0x0c, 0x00]).unwrap();
249
250 Ok(())
251 }
252
close(&self) -> binder::Result<()>253 fn close(&self) -> binder::Result<()> {
254 info!("IBluetoothHci::close");
255
256 let mut service_state = self.service_state.lock().unwrap();
257 service_state.client_state = ClientState::Closed;
258
259 Ok(())
260 }
261
sendAclData(&self, data: &[u8]) -> binder::Result<()>262 fn sendAclData(&self, data: &[u8]) -> binder::Result<()> {
263 info!("IBluetoothHci::sendAclData");
264
265 self.send(Idc::AclData, data)
266 }
267
sendHciCommand(&self, data: &[u8]) -> binder::Result<()>268 fn sendHciCommand(&self, data: &[u8]) -> binder::Result<()> {
269 info!("IBluetoothHci::sendHciCommand");
270
271 self.send(Idc::Command, data)
272 }
273
sendIsoData(&self, data: &[u8]) -> binder::Result<()>274 fn sendIsoData(&self, data: &[u8]) -> binder::Result<()> {
275 info!("IBluetoothHci::sendIsoData");
276
277 self.send(Idc::IsoData, data)
278 }
279
sendScoData(&self, data: &[u8]) -> binder::Result<()>280 fn sendScoData(&self, data: &[u8]) -> binder::Result<()> {
281 info!("IBluetoothHci::sendScoData");
282
283 self.send(Idc::ScoData, data)
284 }
285 }
286