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