@@ -12,12 +12,38 @@ use trouble_host::prelude::*;
1212const CONNECTIONS_MAX : usize = 1 ;
1313
1414/// Max number of L2CAP channels.
15- const L2CAP_CHANNELS_MAX : usize = 2 ; // Signal + att
15+ const L2CAP_CHANNELS_MAX : usize = 4 ; // Signal + att
1616
1717// GATT Server definition
1818#[ gatt_server]
1919struct Server {
2020 battery_service : BatteryService ,
21+ hid_service : HidService ,
22+ }
23+
24+ static DESC : [ u8 ; 67 ] = [
25+ 5u8 , 1u8 , 9u8 , 6u8 , 161u8 , 1u8 , 5u8 , 7u8 , 25u8 , 224u8 , 41u8 , 231u8 , 21u8 , 0u8 , 37u8 , 1u8 , 117u8 , 1u8 , 149u8 , 8u8 ,
26+ 129u8 , 2u8 , 21u8 , 0u8 , 38u8 , 255u8 , 0u8 , 117u8 , 8u8 , 149u8 , 1u8 , 129u8 , 3u8 , 5u8 , 8u8 , 25u8 , 1u8 , 41u8 , 5u8 , 37u8 ,
27+ 1u8 , 117u8 , 1u8 , 149u8 , 5u8 , 145u8 , 2u8 , 149u8 , 3u8 , 145u8 , 3u8 , 5u8 , 7u8 , 25u8 , 0u8 , 41u8 , 221u8 , 38u8 , 255u8 ,
28+ 0u8 , 117u8 , 8u8 , 149u8 , 6u8 , 129u8 , 0u8 , 192u8 ,
29+ ] ;
30+
31+ #[ gatt_service( uuid = service:: HUMAN_INTERFACE_DEVICE ) ]
32+ pub ( crate ) struct HidService {
33+ #[ characteristic( uuid = "2a4a" , read, value = [ 0x01 , 0x01 , 0x00 , 0x03 ] ) ]
34+ pub ( crate ) hid_info : [ u8 ; 4 ] ,
35+ #[ characteristic( uuid = "2a4b" , read, value = DESC ) ]
36+ pub ( crate ) report_map : [ u8 ; 67 ] ,
37+ #[ characteristic( uuid = "2a4c" , write_without_response) ]
38+ pub ( crate ) hid_control_point : u8 ,
39+ #[ characteristic( uuid = "2a4e" , read, write_without_response, value = 1 ) ]
40+ pub ( crate ) protocol_mode : u8 ,
41+ #[ descriptor( uuid = "2908" , read, value = [ 0u8 , 1u8 ] ) ]
42+ #[ characteristic( uuid = "2a4d" , read, notify) ]
43+ pub ( crate ) input_keyboard : [ u8 ; 8 ] ,
44+ #[ descriptor( uuid = "2908" , read, value = [ 0u8 , 2u8 ] ) ]
45+ #[ characteristic( uuid = "2a4d" , read, write, write_without_response) ]
46+ pub ( crate ) output_keyboard : [ u8 ; 1 ] ,
2147}
2248
2349/// Battery service
@@ -47,8 +73,7 @@ impl Key for StoredAddr {
4773 fn deserialize_from ( buffer : & [ u8 ] ) -> Result < ( Self , usize ) , SerializationError > {
4874 if buffer. len ( ) < 6 {
4975 Err ( SerializationError :: BufferTooSmall )
50- }
51- else {
76+ } else {
5277 Ok ( ( StoredAddr ( BdAddr :: new ( buffer[ 0 ..6 ] . try_into ( ) . unwrap ( ) ) ) , 6 ) )
5378 }
5479 }
@@ -75,43 +100,56 @@ impl<'a> Value<'a> for StoredBondInformation {
75100
76101 fn deserialize_from ( buffer : & ' a [ u8 ] ) -> Result < Self , SerializationError >
77102 where
78- Self : Sized
103+ Self : Sized ,
79104 {
80105 if buffer. len ( ) < 17 {
81106 Err ( SerializationError :: BufferTooSmall )
82- }
83- else {
107+ } else {
84108 let ltk = LongTermKey :: from_le_bytes ( buffer[ 0 ..16 ] . try_into ( ) . unwrap ( ) ) ;
85109 let security_level = match buffer[ 16 ] {
86110 0 => SecurityLevel :: NoEncryption ,
87111 1 => SecurityLevel :: Encrypted ,
88112 2 => SecurityLevel :: EncryptedAuthenticated ,
89- _ => return Err ( SerializationError :: InvalidData )
113+ _ => return Err ( SerializationError :: InvalidData ) ,
90114 } ;
91115 Ok ( StoredBondInformation { ltk, security_level } )
92116 }
93117 }
94118}
95119
96120fn flash_range < S : NorFlash > ( ) -> Range < u32 > {
97- 0 ..2 * S :: ERASE_SIZE as u32
121+ 0 ..2 * S :: ERASE_SIZE as u32
98122}
99123
100- async fn store_bonding_info < S : NorFlash > ( storage : & mut S , info : & BondInformation ) -> Result < ( ) , sequential_storage:: Error < S :: Error > > {
101- // Assumes that S::ERASE_SIZE is large enough
102- sequential_storage:: erase_all ( storage, 0 ..S :: ERASE_SIZE as u32 ) . await ?;
103- let mut buffer = [ 0 ; 32 ] ;
124+ async fn store_bonding_info < S : NorFlash > (
125+ storage : & mut S ,
126+ info : & BondInformation ,
127+ ) -> Result < ( ) , sequential_storage:: Error < S :: Error > > {
128+ // Use flash range from 640KB, should be good for both ESP32 & nRF52840 examples
129+ let start_addr = 0xA0000 as u32 ;
130+ let storage_range = start_addr..( start_addr + 8 * S :: ERASE_SIZE as u32 ) ;
131+ sequential_storage:: erase_all ( storage, storage_range. clone ( ) ) . await ?;
132+ let mut buffer = [ 0 ; 32 ] ;
104133 let key = StoredAddr ( info. identity . bd_addr ) ;
105- let value = StoredBondInformation { ltk : info. ltk , security_level : info. security_level } ;
106- sequential_storage:: map:: store_item ( storage, flash_range :: < S > ( ) , & mut NoCache :: new ( ) , & mut buffer, & key, & value) . await ?;
134+ let value = StoredBondInformation {
135+ ltk : info. ltk ,
136+ security_level : info. security_level ,
137+ } ;
138+ sequential_storage:: map:: store_item ( storage, storage_range, & mut NoCache :: new ( ) , & mut buffer, & key, & value) . await ?;
107139 Ok ( ( ) )
108140}
109141
110- async fn load_bonding_info < S : NorFlash > ( storage : & mut S ) -> Option < BondInformation >
111- {
112- let mut buffer = [ 0 ; 32 ] ;
142+ async fn load_bonding_info < S : NorFlash > ( storage : & mut S ) -> Option < BondInformation > {
143+ let mut buffer = [ 0 ; 32 ] ;
113144 let mut cache = NoCache :: new ( ) ;
114- let mut iter = sequential_storage:: map:: fetch_all_items :: < StoredAddr , _ , _ > ( storage, flash_range :: < S > ( ) , & mut cache, & mut buffer) . await . ok ( ) ?;
145+ let mut iter = sequential_storage:: map:: fetch_all_items :: < StoredAddr , _ , _ > (
146+ storage,
147+ flash_range :: < S > ( ) ,
148+ & mut cache,
149+ & mut buffer,
150+ )
151+ . await
152+ . ok ( ) ?;
115153 while let Some ( ( key, value) ) = iter. next :: < StoredBondInformation > ( & mut buffer) . await . ok ( ) ? {
116154 return Some ( BondInformation {
117155 identity : Identity {
@@ -120,7 +158,7 @@ async fn load_bonding_info<S: NorFlash>(storage: &mut S) -> Option<BondInformati
120158 } ,
121159 security_level : value. security_level ,
122160 is_bonded : true ,
123- ltk : value. ltk
161+ ltk : value. ltk ,
124162 } ) ;
125163 }
126164 None
@@ -147,8 +185,7 @@ where
147185 info ! ( "Loaded bond information" ) ;
148186 stack. add_bond_information ( bond_info) . unwrap ( ) ;
149187 true
150- }
151- else {
188+ } else {
152189 info ! ( "No bond information found" ) ;
153190 false
154191 } ;
@@ -160,9 +197,9 @@ where
160197 info ! ( "Starting advertising and GATT service" ) ;
161198 let server = Server :: new_with_config ( GapConfig :: Peripheral ( PeripheralConfig {
162199 name : "TrouBLE" ,
163- appearance : & appearance:: power_device :: GENERIC_POWER_DEVICE ,
200+ appearance : & appearance:: human_interface_device :: GENERIC_HUMAN_INTERFACE_DEVICE ,
164201 } ) )
165- . unwrap ( ) ;
202+ . unwrap ( ) ;
166203
167204 let _ = join ( ble_task ( runner) , async {
168205 loop {
@@ -176,6 +213,7 @@ where
176213 // run until any task ends (usually because the connection has been closed),
177214 // then return to advertising state.
178215 select ( a, b) . await ;
216+ info ! ( "Connection dropped" ) ;
179217 }
180218 Err ( e) => {
181219 #[ cfg( feature = "defmt" ) ]
@@ -185,7 +223,7 @@ where
185223 }
186224 }
187225 } )
188- . await ;
226+ . await ;
189227}
190228
191229/// This is a background task that is required to run forever alongside any other BLE tasks.
@@ -217,13 +255,18 @@ async fn ble_task<C: Controller, P: PacketPool>(mut runner: Runner<'_, C, P>) {
217255///
218256/// This function will handle the GATT events and process them.
219257/// This is how we interact with read and write requests.
220- async fn gatt_events_task < S : NorFlash > ( storage : & mut S , server : & Server < ' _ > , conn : & GattConnection < ' _ , ' _ , DefaultPacketPool > , bond_stored : & mut bool ) -> Result < ( ) , Error > {
258+ async fn gatt_events_task < S : NorFlash > (
259+ storage : & mut S ,
260+ server : & Server < ' _ > ,
261+ conn : & GattConnection < ' _ , ' _ , DefaultPacketPool > ,
262+ bond_stored : & mut bool ,
263+ ) -> Result < ( ) , Error > {
221264 let level = server. battery_service . level ;
222265 let reason = loop {
223266 match conn. next ( ) . await {
224267 GattConnectionEvent :: Disconnected { reason } => break reason,
225268 #[ cfg( feature = "security" ) ]
226- GattConnectionEvent :: PairingComplete { security_level, bond} => {
269+ GattConnectionEvent :: PairingComplete { security_level, bond } => {
227270 info ! ( "[gatt] pairing complete: {:?}" , security_level) ;
228271 if let Some ( bond) = bond {
229272 store_bonding_info ( storage, & bond) . await . unwrap ( ) ;
@@ -294,7 +337,10 @@ async fn advertise<'values, 'server, C: Controller>(
294337 let len = AdStructure :: encode_slice (
295338 & [
296339 AdStructure :: Flags ( LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED ) ,
297- AdStructure :: ServiceUuids16 ( & [ [ 0x0f , 0x18 ] ] ) ,
340+ AdStructure :: ServiceUuids16 ( & [
341+ service:: BATTERY . to_le_bytes ( ) ,
342+ service:: HUMAN_INTERFACE_DEVICE . to_le_bytes ( ) ,
343+ ] ) ,
298344 AdStructure :: CompleteLocalName ( name. as_bytes ( ) ) ,
299345 ] ,
300346 & mut advertiser_data[ ..] ,
0 commit comments