• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::mem::ManuallyDrop;
2 use std::rc::Rc;
3 use std::slice;
4 
5 use crate::manager::LinkManager;
6 use crate::packets::{hci, lmp};
7 
8 /// Link Manager callbacks
9 #[repr(C)]
10 #[derive(Clone)]
11 pub struct LinkManagerOps {
12     user_pointer: *mut (),
13     get_handle: unsafe extern "C" fn(user: *mut (), address: *const [u8; 6]) -> u16,
14     get_address: unsafe extern "C" fn(user: *mut (), handle: u16, result: *mut [u8; 6]),
15     extended_features: unsafe extern "C" fn(user: *mut (), features_page: u8) -> u64,
16     send_hci_event: unsafe extern "C" fn(user: *mut (), data: *const u8, len: usize),
17     send_lmp_packet:
18         unsafe extern "C" fn(user: *mut (), to: *const [u8; 6], data: *const u8, len: usize),
19 }
20 
21 impl LinkManagerOps {
get_address(&self, handle: u16) -> hci::Address22     pub(crate) fn get_address(&self, handle: u16) -> hci::Address {
23         let mut result = hci::EMPTY_ADDRESS;
24         unsafe { (self.get_address)(self.user_pointer, handle, &mut result.bytes as *mut _) };
25         result
26     }
27 
get_handle(&self, addr: hci::Address) -> u1628     pub(crate) fn get_handle(&self, addr: hci::Address) -> u16 {
29         unsafe { (self.get_handle)(self.user_pointer, &addr.bytes as *const _) }
30     }
31 
extended_features(&self, features_page: u8) -> u6432     pub(crate) fn extended_features(&self, features_page: u8) -> u64 {
33         unsafe { (self.extended_features)(self.user_pointer, features_page) }
34     }
35 
send_hci_event(&self, packet: &[u8])36     pub(crate) fn send_hci_event(&self, packet: &[u8]) {
37         unsafe { (self.send_hci_event)(self.user_pointer, packet.as_ptr(), packet.len()) }
38     }
39 
send_lmp_packet(&self, to: hci::Address, packet: &[u8])40     pub(crate) fn send_lmp_packet(&self, to: hci::Address, packet: &[u8]) {
41         unsafe {
42             (self.send_lmp_packet)(
43                 self.user_pointer,
44                 &to.bytes as *const _,
45                 packet.as_ptr(),
46                 packet.len(),
47             )
48         }
49     }
50 }
51 
52 /// Create a new link manager instance
53 /// # Arguments
54 /// * `ops` - Function callbacks required by the link manager
55 #[no_mangle]
link_manager_create(ops: LinkManagerOps) -> *const LinkManager56 pub extern "C" fn link_manager_create(ops: LinkManagerOps) -> *const LinkManager {
57     Rc::into_raw(Rc::new(LinkManager::new(ops)))
58 }
59 
60 /// Register a new link with a peer inside the link manager
61 /// # Arguments
62 /// * `lm` - link manager pointer
63 /// * `peer` - peer address as array of 6 bytes
64 /// # Safety
65 /// - This should be called from the thread of creation
66 /// - `lm` must be a valid pointer
67 /// - `peer` must be valid for reads for 6 bytes
68 #[no_mangle]
link_manager_add_link( lm: *const LinkManager, peer: *const [u8; 6], ) -> bool69 pub unsafe extern "C" fn link_manager_add_link(
70     lm: *const LinkManager,
71     peer: *const [u8; 6],
72 ) -> bool {
73     let lm = ManuallyDrop::new(Rc::from_raw(lm));
74     lm.add_link(hci::Address { bytes: *peer }).is_ok()
75 }
76 
77 /// Unregister a link with a peer inside the link manager
78 /// Returns true if successful
79 /// # Arguments
80 /// * `lm` - link manager pointer
81 /// * `peer` - peer address as array of 6 bytes
82 /// # Safety
83 /// - This should be called from the thread of creation
84 /// - `lm` must be a valid pointer
85 /// - `peer` must be valid for reads for 6 bytes
86 #[no_mangle]
link_manager_remove_link( lm: *const LinkManager, peer: *const [u8; 6], ) -> bool87 pub unsafe extern "C" fn link_manager_remove_link(
88     lm: *const LinkManager,
89     peer: *const [u8; 6],
90 ) -> bool {
91     let lm = ManuallyDrop::new(Rc::from_raw(lm));
92     lm.remove_link(hci::Address { bytes: *peer }).is_ok()
93 }
94 
95 /// Run the Link Manager procedures
96 /// # Arguments
97 /// * `lm` - link manager pointer
98 /// # Safety
99 /// - This should be called from the thread of creation
100 /// - `lm` must be a valid pointer
101 #[no_mangle]
link_manager_tick(lm: *const LinkManager)102 pub unsafe extern "C" fn link_manager_tick(lm: *const LinkManager) {
103     let lm = ManuallyDrop::new(Rc::from_raw(lm));
104     lm.as_ref().tick();
105 }
106 
107 /// Process an HCI packet with the link manager
108 /// Returns true if successful
109 /// # Arguments
110 /// * `lm` - link manager pointer
111 /// * `data` - HCI packet data
112 /// * `len` - HCI packet len
113 /// # Safety
114 /// - This should be called from the thread of creation
115 /// - `lm` must be a valid pointer
116 /// - `data` must be valid for reads of len `len`
117 #[no_mangle]
link_manager_ingest_hci( lm: *const LinkManager, data: *const u8, len: usize, ) -> bool118 pub unsafe extern "C" fn link_manager_ingest_hci(
119     lm: *const LinkManager,
120     data: *const u8,
121     len: usize,
122 ) -> bool {
123     let lm = ManuallyDrop::new(Rc::from_raw(lm));
124     let data = slice::from_raw_parts(data, len);
125 
126     if let Ok(packet) = hci::CommandPacket::parse(data) {
127         lm.ingest_hci(packet).is_ok()
128     } else {
129         false
130     }
131 }
132 
133 /// Process an LMP packet from a peer with the link manager
134 /// Returns true if successful
135 /// # Arguments
136 /// * `lm` - link manager pointer
137 /// * `from` - Address of peer as array of 6 bytes
138 /// * `data` - HCI packet data
139 /// * `len` - HCI packet len
140 /// # Safety
141 /// - This should be called from the thread of creation
142 /// - `lm` must be a valid pointers
143 /// - `from` must be valid pointer for reads for 6 bytes
144 /// - `data` must be valid for reads of len `len`
145 #[no_mangle]
link_manager_ingest_lmp( lm: *const LinkManager, from: *const [u8; 6], data: *const u8, len: usize, ) -> bool146 pub unsafe extern "C" fn link_manager_ingest_lmp(
147     lm: *const LinkManager,
148     from: *const [u8; 6],
149     data: *const u8,
150     len: usize,
151 ) -> bool {
152     let lm = ManuallyDrop::new(Rc::from_raw(lm));
153     let data = slice::from_raw_parts(data, len);
154 
155     if let Ok(packet) = lmp::PacketPacket::parse(data) {
156         lm.ingest_lmp(hci::Address { bytes: *from }, packet).is_ok()
157     } else {
158         false
159     }
160 }
161 
162 /// Deallocate the link manager instance
163 /// # Arguments
164 /// * `lm` - link manager pointer
165 /// # Safety
166 /// - This should be called from the thread of creation
167 /// - `lm` must be a valid pointers and must not be reused afterwards
168 #[no_mangle]
link_manager_destroy(lm: *const LinkManager)169 pub unsafe extern "C" fn link_manager_destroy(lm: *const LinkManager) {
170     let _ = Rc::from_raw(lm);
171 }
172