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