1 // Copyright 2023 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 // TODO(b/290018030): Remove this and add proper safety comments.
16 #![allow(clippy::undocumented_unsafe_blocks)]
17
18 use std::convert::TryFrom;
19 use std::mem::ManuallyDrop;
20 use std::rc::Rc;
21 use std::slice;
22
23 use crate::llcp::manager::LinkLayer;
24 use crate::lmp::manager::LinkManager;
25 use crate::packets::{hci, llcp, lmp};
26
27 /// Link Manager callbacks
28 #[repr(C)]
29 #[derive(Clone)]
30 pub struct ControllerOps {
31 user_pointer: *mut (),
32 get_handle: unsafe extern "C" fn(user: *mut (), address: *const [u8; 6]) -> u16,
33 get_address: unsafe extern "C" fn(user: *mut (), handle: u16, result: *mut [u8; 6]),
34 get_extended_features: unsafe extern "C" fn(user: *mut (), features_page: u8) -> u64,
35 get_le_features: unsafe extern "C" fn(user: *mut ()) -> u64,
36 get_le_event_mask: unsafe extern "C" fn(user: *mut ()) -> u64,
37 send_hci_event: unsafe extern "C" fn(user: *mut (), data: *const u8, len: usize),
38 send_lmp_packet:
39 unsafe extern "C" fn(user: *mut (), to: *const [u8; 6], data: *const u8, len: usize),
40 send_llcp_packet: unsafe extern "C" fn(user: *mut (), handle: u16, data: *const u8, len: usize),
41 }
42
43 impl ControllerOps {
get_address(&self, handle: u16) -> Option<hci::Address>44 pub(crate) fn get_address(&self, handle: u16) -> Option<hci::Address> {
45 let mut result = [0; 6];
46 unsafe { (self.get_address)(self.user_pointer, handle, &mut result as *mut _) };
47 let addr = hci::Address::from(&result);
48 (addr != hci::EMPTY_ADDRESS).then_some(addr)
49 }
50
get_handle(&self, addr: hci::Address) -> u1651 pub(crate) fn get_handle(&self, addr: hci::Address) -> u16 {
52 let addr_bytes: [u8; 6] = addr.into();
53 unsafe { (self.get_handle)(self.user_pointer, &addr_bytes as *const _) }
54 }
55
get_extended_features(&self, features_page: u8) -> u6456 pub(crate) fn get_extended_features(&self, features_page: u8) -> u64 {
57 unsafe { (self.get_extended_features)(self.user_pointer, features_page) }
58 }
59
get_le_features(&self) -> u6460 pub(crate) fn get_le_features(&self) -> u64 {
61 unsafe { (self.get_le_features)(self.user_pointer) }
62 }
63
64 #[allow(dead_code)]
get_le_event_mask(&self) -> u6465 pub(crate) fn get_le_event_mask(&self) -> u64 {
66 unsafe { (self.get_le_event_mask)(self.user_pointer) }
67 }
68
send_hci_event(&self, packet: &[u8])69 pub(crate) fn send_hci_event(&self, packet: &[u8]) {
70 unsafe { (self.send_hci_event)(self.user_pointer, packet.as_ptr(), packet.len()) }
71 }
72
send_lmp_packet(&self, to: hci::Address, packet: &[u8])73 pub(crate) fn send_lmp_packet(&self, to: hci::Address, packet: &[u8]) {
74 let to_bytes: [u8; 6] = to.into();
75 unsafe {
76 (self.send_lmp_packet)(
77 self.user_pointer,
78 &to_bytes as *const _,
79 packet.as_ptr(),
80 packet.len(),
81 )
82 }
83 }
84
send_llcp_packet(&self, handle: u16, packet: &[u8])85 pub(crate) fn send_llcp_packet(&self, handle: u16, packet: &[u8]) {
86 unsafe { (self.send_llcp_packet)(self.user_pointer, handle, packet.as_ptr(), packet.len()) }
87 }
88 }
89
90 /// Create a new link manager instance
91 /// # Arguments
92 /// * `ops` - Function callbacks required by the link manager
93 #[no_mangle]
link_manager_create(ops: ControllerOps) -> *const LinkManager94 pub extern "C" fn link_manager_create(ops: ControllerOps) -> *const LinkManager {
95 Rc::into_raw(Rc::new(LinkManager::new(ops)))
96 }
97
98 /// Register a new link with a peer inside the link manager
99 /// # Arguments
100 /// * `lm` - link manager pointer
101 /// * `peer` - peer address as array of 6 bytes
102 /// # Safety
103 /// - This should be called from the thread of creation
104 /// - `lm` must be a valid pointer
105 /// - `peer` must be valid for reads for 6 bytes
106 #[no_mangle]
link_manager_add_link( lm: *const LinkManager, peer: *const [u8; 6], ) -> bool107 pub unsafe extern "C" fn link_manager_add_link(
108 lm: *const LinkManager,
109 peer: *const [u8; 6],
110 ) -> bool {
111 let lm = ManuallyDrop::new(unsafe { Rc::from_raw(lm) });
112 unsafe { lm.add_link(hci::Address::from(&*peer)).is_ok() }
113 }
114
115 /// Unregister a link with a peer inside the link manager
116 /// Returns true if successful
117 /// # Arguments
118 /// * `lm` - link manager pointer
119 /// * `peer` - peer address as array of 6 bytes
120 /// # Safety
121 /// - This should be called from the thread of creation
122 /// - `lm` must be a valid pointer
123 /// - `peer` must be valid for reads for 6 bytes
124 #[no_mangle]
link_manager_remove_link( lm: *const LinkManager, peer: *const [u8; 6], ) -> bool125 pub unsafe extern "C" fn link_manager_remove_link(
126 lm: *const LinkManager,
127 peer: *const [u8; 6],
128 ) -> bool {
129 let lm = ManuallyDrop::new(unsafe { Rc::from_raw(lm) });
130 unsafe { lm.remove_link(hci::Address::from(&*peer)).is_ok() }
131 }
132
133 /// Run the Link Manager procedures
134 /// # Arguments
135 /// * `lm` - link manager pointer
136 /// # Safety
137 /// - This should be called from the thread of creation
138 /// - `lm` must be a valid pointer
139 #[no_mangle]
link_manager_tick(lm: *const LinkManager)140 pub unsafe extern "C" fn link_manager_tick(lm: *const LinkManager) {
141 let lm = ManuallyDrop::new(unsafe { Rc::from_raw(lm) });
142 lm.as_ref().tick();
143 }
144
145 /// Process an HCI packet with the link manager
146 /// Returns true if successful
147 /// # Arguments
148 /// * `lm` - link manager pointer
149 /// * `data` - HCI packet data
150 /// * `len` - HCI packet len
151 /// # Safety
152 /// - This should be called from the thread of creation
153 /// - `lm` must be a valid pointer
154 /// - `data` must be valid for reads of len `len`
155 #[no_mangle]
link_manager_ingest_hci( lm: *const LinkManager, data: *const u8, len: usize, ) -> bool156 pub unsafe extern "C" fn link_manager_ingest_hci(
157 lm: *const LinkManager,
158 data: *const u8,
159 len: usize,
160 ) -> bool {
161 let lm = ManuallyDrop::new(unsafe { Rc::from_raw(lm) });
162 let data = unsafe { slice::from_raw_parts(data, len) };
163
164 if let Ok(packet) = hci::Command::parse(data) {
165 lm.ingest_hci(packet).is_ok()
166 } else {
167 false
168 }
169 }
170
171 /// Process an LMP packet from a peer with the link manager
172 /// Returns true if successful
173 /// # Arguments
174 /// * `lm` - link manager pointer
175 /// * `from` - Address of peer as array of 6 bytes
176 /// * `data` - HCI packet data
177 /// * `len` - HCI packet len
178 /// # Safety
179 /// - This should be called from the thread of creation
180 /// - `lm` must be a valid pointers
181 /// - `from` must be valid pointer for reads for 6 bytes
182 /// - `data` must be valid for reads of len `len`
183 #[no_mangle]
link_manager_ingest_lmp( lm: *const LinkManager, from: *const [u8; 6], data: *const u8, len: usize, ) -> bool184 pub unsafe extern "C" fn link_manager_ingest_lmp(
185 lm: *const LinkManager,
186 from: *const [u8; 6],
187 data: *const u8,
188 len: usize,
189 ) -> bool {
190 let lm = ManuallyDrop::new(unsafe { Rc::from_raw(lm) });
191 let data = unsafe { slice::from_raw_parts(data, len) };
192
193 if let Ok(packet) = lmp::LmpPacket::parse(data) {
194 unsafe { lm.ingest_lmp(hci::Address::from(&*from), packet).is_ok() }
195 } else {
196 false
197 }
198 }
199
200 /// Deallocate the link manager instance
201 /// # Arguments
202 /// * `lm` - link manager pointer
203 /// # Safety
204 /// - This should be called from the thread of creation
205 /// - `lm` must be a valid pointers and must not be reused afterwards
206 #[no_mangle]
link_manager_destroy(lm: *const LinkManager)207 pub unsafe extern "C" fn link_manager_destroy(lm: *const LinkManager) {
208 unsafe {
209 let _ = Rc::from_raw(lm);
210 }
211 }
212
213 /// Create a new link manager instance
214 /// # Arguments
215 /// * `ops` - Function callbacks required by the link manager
216 #[no_mangle]
link_layer_create(ops: ControllerOps) -> *const LinkLayer217 pub extern "C" fn link_layer_create(ops: ControllerOps) -> *const LinkLayer {
218 Rc::into_raw(Rc::new(LinkLayer::new(ops)))
219 }
220
221 /// Register a new link with a peer inside the link layer
222 /// # Arguments
223 /// * `ll` - link layer pointer
224 /// * `handle` - connection handle for the link
225 /// * `peer_address` - peer address as array of 6 bytes
226 /// * `role` - connection role (peripheral or centrl) for the link
227 /// # Safety
228 /// - This should be called from the thread of creation
229 /// - `ll` must be a valid pointer
230 /// - `peer` must be valid for reads for 6 bytes
231 /// - `role` must be 0 (central) or 1 (peripheral)
232 #[no_mangle]
link_layer_add_link( ll: *const LinkLayer, handle: u16, peer_address: *const [u8; 6], role: u8, ) -> bool233 pub unsafe extern "C" fn link_layer_add_link(
234 ll: *const LinkLayer,
235 handle: u16,
236 peer_address: *const [u8; 6],
237 role: u8,
238 ) -> bool {
239 let mut ll = ManuallyDrop::new(unsafe { Rc::from_raw(ll) });
240 let ll = Rc::get_mut(&mut ll).unwrap();
241 let role = hci::Role::try_from(role).unwrap_or(hci::Role::Peripheral);
242 unsafe { ll.add_link(handle, hci::Address::from(&*peer_address), role).is_ok() }
243 }
244
245 /// Unregister a link with a peer inside the link layer
246 /// Returns true if successful
247 /// # Arguments
248 /// * `ll` - link layer pointer
249 /// * `peer` - peer address as array of 6 bytes
250 /// # Safety
251 /// - This should be called from the thread of creation
252 /// - `ll` must be a valid pointer
253 /// - `peer` must be valid for reads for 6 bytes
254 #[no_mangle]
link_layer_remove_link(ll: *const LinkLayer, handle: u16) -> bool255 pub unsafe extern "C" fn link_layer_remove_link(ll: *const LinkLayer, handle: u16) -> bool {
256 let mut ll = ManuallyDrop::new(unsafe { Rc::from_raw(ll) });
257 let ll = Rc::get_mut(&mut ll).unwrap();
258 ll.remove_link(handle).is_ok()
259 }
260
261 /// Run the Link Manager procedures
262 /// # Arguments
263 /// * `ll` - link layer pointer
264 /// # Safety
265 /// - This should be called from the thread of creation
266 /// - `ll` must be a valid pointer
267 #[no_mangle]
link_layer_tick(ll: *const LinkLayer)268 pub unsafe extern "C" fn link_layer_tick(ll: *const LinkLayer) {
269 let mut ll = ManuallyDrop::new(unsafe { Rc::from_raw(ll) });
270 let ll = Rc::get_mut(&mut ll).unwrap();
271 ll.tick();
272 }
273
274 /// Process an HCI packet with the link layer
275 /// Returns true if successful
276 /// # Arguments
277 /// * `ll` - link layer pointer
278 /// * `data` - HCI packet data
279 /// * `len` - HCI packet len
280 /// # Safety
281 /// - This should be called from the thread of creation
282 /// - `ll` must be a valid pointer
283 /// - `data` must be valid for reads of len `len`
284 #[no_mangle]
link_layer_ingest_hci( ll: *const LinkLayer, data: *const u8, len: usize, ) -> bool285 pub unsafe extern "C" fn link_layer_ingest_hci(
286 ll: *const LinkLayer,
287 data: *const u8,
288 len: usize,
289 ) -> bool {
290 let mut ll = ManuallyDrop::new(unsafe { Rc::from_raw(ll) });
291 let ll = Rc::get_mut(&mut ll).unwrap();
292 let data = unsafe { slice::from_raw_parts(data, len) };
293
294 if let Ok(packet) = hci::Command::parse(data) {
295 ll.ingest_hci(packet).is_ok()
296 } else {
297 false
298 }
299 }
300
301 /// Process an LLCP packet from a peer with the link layer
302 /// Returns true if successful
303 /// # Arguments
304 /// * `ll` - link layer pointer
305 /// * `handle` - ACL handle of the connection
306 /// * `data` - HCI packet data
307 /// * `len` - HCI packet len
308 /// # Safety
309 /// - This should be called from the thread of creation
310 /// - `ll` must be a valid pointers
311 /// - `data` must be valid for reads of len `len`
312 #[no_mangle]
link_layer_ingest_llcp( ll: *const LinkLayer, handle: u16, data: *const u8, len: usize, ) -> bool313 pub unsafe extern "C" fn link_layer_ingest_llcp(
314 ll: *const LinkLayer,
315 handle: u16,
316 data: *const u8,
317 len: usize,
318 ) -> bool {
319 let mut ll = ManuallyDrop::new(unsafe { Rc::from_raw(ll) });
320 let ll = Rc::get_mut(&mut ll).unwrap();
321 let data = unsafe { slice::from_raw_parts(data, len) };
322
323 if let Ok(packet) = llcp::LlcpPacket::parse(data) {
324 ll.ingest_llcp(handle, packet).is_ok()
325 } else {
326 false
327 }
328 }
329
330 /// Query the connection handle for a CIS established with
331 /// the input CIS and CIG identifiers.
332 /// Returns true if successful
333 /// # Arguments
334 /// * `ll` - link layer pointer
335 /// * `cig_id` - Identifier of the established Cig
336 /// * `cis_id` - Identifier of the established Cis
337 /// * `cis_connection_handle` - Returns the handle of the CIS if connected
338 /// # Safety
339 /// - This should be called from the thread of creation
340 /// - `ll` must be a valid pointers
341 #[no_mangle]
link_layer_get_cis_connection_handle( ll: *const LinkLayer, cig_id: u8, cis_id: u8, cis_connection_handle: *mut u16, ) -> bool342 pub unsafe extern "C" fn link_layer_get_cis_connection_handle(
343 ll: *const LinkLayer,
344 cig_id: u8,
345 cis_id: u8,
346 cis_connection_handle: *mut u16,
347 ) -> bool {
348 let mut ll = ManuallyDrop::new(unsafe { Rc::from_raw(ll) });
349 let ll = Rc::get_mut(&mut ll).unwrap();
350 ll.get_cis_connection_handle(cig_id, cis_id)
351 .map(|handle| unsafe {
352 *cis_connection_handle = handle;
353 })
354 .is_some()
355 }
356
357 /// Query the CIS and CIG identifiers for a CIS established with
358 /// the input CIS connection handle.
359 /// Returns true if successful
360 /// # Arguments
361 /// * `ll` - link layer pointer
362 /// * `cis_connection_handle` - CIS connection handle
363 /// * `cig_id` - Returns the CIG identifier
364 /// * `cis_id` - Returns the CIS identifier
365 /// # Safety
366 /// - This should be called from the thread of creation
367 /// - `ll` must be a valid pointers
368 #[no_mangle]
link_layer_get_cis_information( ll: *const LinkLayer, cis_connection_handle: u16, acl_connection_handle: *mut u16, cig_id: *mut u8, cis_id: *mut u8, max_sdu_tx: *mut u16, ) -> bool369 pub unsafe extern "C" fn link_layer_get_cis_information(
370 ll: *const LinkLayer,
371 cis_connection_handle: u16,
372 acl_connection_handle: *mut u16,
373 cig_id: *mut u8,
374 cis_id: *mut u8,
375 max_sdu_tx: *mut u16,
376 ) -> bool {
377 let mut ll = ManuallyDrop::new(unsafe { Rc::from_raw(ll) });
378 let ll = Rc::get_mut(&mut ll).unwrap();
379 ll.get_cis(cis_connection_handle)
380 .map(|cis| {
381 if let Some(handle) = cis.acl_connection_handle {
382 unsafe {
383 *acl_connection_handle = handle;
384 }
385 }
386 unsafe {
387 *cig_id = cis.cig_id;
388 *cis_id = cis.cis_id;
389 *max_sdu_tx = cis.max_sdu_tx().unwrap_or(0);
390 }
391 })
392 .is_some()
393 }
394
395 /// Deallocate the link layer instance
396 /// # Arguments
397 /// * `ll` - link layer pointer
398 /// # Safety
399 /// - This should be called from the thread of creation
400 /// - `ll` must be a valid pointers and must not be reused afterwards
401 #[no_mangle]
link_layer_destroy(ll: *const LinkLayer)402 pub unsafe extern "C" fn link_layer_destroy(ll: *const LinkLayer) {
403 unsafe {
404 let _ = Rc::from_raw(ll);
405 }
406 }
407