• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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