@@ -53,7 +53,19 @@ BLEGap::BLEGap(void)
5353 _cfg_central.wr_cmd_qsize = BLE_GATTC_WRITE_CMD_TX_QUEUE_SIZE_DEFAULT;
5454#endif
5555
56-
56+ _sec_param = (ble_gap_sec_params_t )
57+ {
58+ .bond = 1 ,
59+ .mitm = 0 ,
60+ .lesc = 0 ,
61+ .keypress = 0 ,
62+ .io_caps = BLE_GAP_IO_CAPS_NONE,
63+ .oob = 0 ,
64+ .min_key_size = 7 ,
65+ .max_key_size = 16 ,
66+ .kdist_own = { .enc = 1 , .id = 1 },
67+ .kdist_peer = { .enc = 1 , .id = 1 },
68+ };
5769}
5870
5971
@@ -83,19 +95,19 @@ uint16_t BLEGap::getMaxMtuByConnCfg(uint8_t conn_cfg)
8395 return (conn_cfg == CONN_CFG_PERIPHERAL) ? _cfg_prph.mtu_max : _cfg_central.mtu_max ;
8496}
8597
86- uint16_t BLEGap::getMaxMtu (uint8_t conn_handle )
98+ uint16_t BLEGap::getMaxMtu (uint8_t conn_hdl )
8799{
88- return (getRole (conn_handle ) == BLE_GAP_ROLE_PERIPH) ? _cfg_prph.mtu_max : _cfg_central.mtu_max ;
100+ return (getRole (conn_hdl ) == BLE_GAP_ROLE_PERIPH) ? _cfg_prph.mtu_max : _cfg_central.mtu_max ;
89101}
90102
91- uint8_t BLEGap::getHvnQueueSize (uint8_t conn_handle )
103+ uint8_t BLEGap::getHvnQueueSize (uint8_t conn_hdl )
92104{
93- return (getRole (conn_handle ) == BLE_GAP_ROLE_PERIPH) ? _cfg_prph.hvn_tx_qsize : _cfg_central.hvn_tx_qsize ;
105+ return (getRole (conn_hdl ) == BLE_GAP_ROLE_PERIPH) ? _cfg_prph.hvn_tx_qsize : _cfg_central.hvn_tx_qsize ;
94106}
95107
96- uint8_t BLEGap::getWriteCmdQueueSize (uint8_t conn_handle )
108+ uint8_t BLEGap::getWriteCmdQueueSize (uint8_t conn_hdl )
97109{
98- return (getRole (conn_handle ) == BLE_GAP_ROLE_PERIPH) ? _cfg_prph.wr_cmd_qsize : _cfg_central.wr_cmd_qsize ;
110+ return (getRole (conn_hdl ) == BLE_GAP_ROLE_PERIPH) ? _cfg_prph.wr_cmd_qsize : _cfg_central.wr_cmd_qsize ;
99111}
100112
101113
@@ -142,52 +154,76 @@ bool BLEGap::setAddr(uint8_t mac[6], uint8_t type)
142154 return true ;
143155}
144156
145- bool BLEGap::connected (uint16_t conn_handle )
157+ bool BLEGap::connected (uint16_t conn_hdl )
146158{
147- return _peers[conn_handle ].connected ;
159+ return _peers[conn_hdl ].connected ;
148160}
149161
150- uint8_t BLEGap::getRole (uint16_t conn_handle )
162+ bool BLEGap::bonded (uint16_t conn_hdl )
151163{
152- return _peers[conn_handle]. role ;
164+ return _peers[conn_hdl]. bonded ;
153165}
154166
155- uint8_t BLEGap::getPeerAddr (uint16_t conn_handle, uint8_t addr[ 6 ] )
167+ bool BLEGap::requestPairing (uint16_t conn_hdl )
156168{
157- memcpy (addr, _peers[conn_handle].addr .addr , BLE_GAP_ADDR_LEN);
158- return _peers[conn_handle].addr .addr_type ;
169+ gap_peer_t * peer = &_peers[conn_hdl];
170+
171+ // skip if already bonded
172+ if ( peer->bonded ) return true ;
173+
174+ VERIFY_STATUS ( sd_ble_gap_authenticate (conn_hdl, &_sec_param ), false );
175+ uint32_t start = millis ();
176+
177+ // timeout in 30 seconds
178+ while ( ! ((volatile bool ) peer->bonded ) && (start + 30000 > millis ()) )
179+ {
180+ yield ();
181+ }
182+
183+ return peer->bonded ;
159184}
160185
161- ble_gap_addr_t BLEGap::getPeerAddr (uint16_t conn_handle )
186+ uint8_t BLEGap::getRole (uint16_t conn_hdl )
162187{
163- return _peers[conn_handle]. addr ;
188+ return _peers[conn_hdl]. role ;
164189}
165190
166- bool BLEGap::getHvnPacket (uint16_t conn_handle )
191+ uint8_t BLEGap::getPeerAddr (uint16_t conn_hdl, uint8_t addr[ 6 ] )
167192{
168- VERIFY ( (conn_handle < BLE_MAX_CONN) && (_peers[conn_handle].hvn_tx_sem != NULL ) );
193+ memcpy (addr, _peers[conn_hdl].addr .addr , BLE_GAP_ADDR_LEN);
194+ return _peers[conn_hdl].addr .addr_type ;
195+ }
169196
170- return xSemaphoreTake (_peers[conn_handle].hvn_tx_sem , ms2tick (BLE_GENERIC_TIMEOUT));
197+ ble_gap_addr_t BLEGap::getPeerAddr (uint16_t conn_hdl)
198+ {
199+ return _peers[conn_hdl].addr ;
171200}
172201
173- bool BLEGap::getWriteCmdPacket (uint16_t conn_handle)
202+ bool BLEGap::getHvnPacket (uint16_t conn_hdl)
203+ {
204+ VERIFY ( (conn_hdl < BLE_MAX_CONN) && (_peers[conn_hdl].hvn_tx_sem != NULL ) );
205+
206+ return xSemaphoreTake (_peers[conn_hdl].hvn_tx_sem , ms2tick (BLE_GENERIC_TIMEOUT));
207+ }
208+
209+ bool BLEGap::getWriteCmdPacket (uint16_t conn_hdl)
174210{
175211#if SD_VER < 500
176- return getHvnPacket (conn_handle );
212+ return getHvnPacket (conn_hdl );
177213#else
178- VERIFY ( (conn_handle < BLE_MAX_CONN) && (_peers[conn_handle ].wrcmd_tx_sem != NULL ) );
179- return xSemaphoreTake (_peers[conn_handle ].wrcmd_tx_sem , ms2tick (BLE_GENERIC_TIMEOUT));
214+ VERIFY ( (conn_hdl < BLE_MAX_CONN) && (_peers[conn_hdl ].wrcmd_tx_sem != NULL ) );
215+ return xSemaphoreTake (_peers[conn_hdl ].wrcmd_tx_sem , ms2tick (BLE_GENERIC_TIMEOUT));
180216#endif
181217}
182218
183- uint16_t BLEGap::getMTU (uint16_t conn_handle )
219+ uint16_t BLEGap::getMTU (uint16_t conn_hdl )
184220{
185- return _peers[conn_handle ].att_mtu ;
221+ return _peers[conn_hdl ].att_mtu ;
186222}
187223
188- uint16_t BLEGap::getPeerName (uint16_t conn_handle , char * buf, uint16_t bufsize)
224+ uint16_t BLEGap::getPeerName (uint16_t conn_hdl , char * buf, uint16_t bufsize)
189225{
190- return Bluefruit.Gatt .readCharByUuid (conn_handle , BLEUuid (BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME), buf, bufsize);
226+ return Bluefruit.Gatt .readCharByUuid (conn_hdl , BLEUuid (BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME), buf, bufsize);
191227}
192228
193229/* *
@@ -197,9 +233,9 @@ uint16_t BLEGap::getPeerName(uint16_t conn_handle, char* buf, uint16_t bufsize)
197233void BLEGap::_eventHandler (ble_evt_t * evt)
198234{
199235 // conn handle has fixed offset regardless of event type
200- const uint16_t conn_handle = evt->evt .common_evt .conn_handle ;
236+ const uint16_t conn_hdl = evt->evt .common_evt .conn_handle ;
201237
202- gap_peer_t * peer = &_peers[conn_handle ];
238+ gap_peer_t * peer = (conn_hdl == BLE_CONN_HANDLE_INVALID) ? NULL : &_peers[conn_hdl ];
203239
204240 switch (evt->header .evt_id )
205241 {
@@ -215,13 +251,13 @@ void BLEGap::_eventHandler(ble_evt_t* evt)
215251 // Init transmission buffer for notification
216252 #if SD_VER < 500
217253 uint8_t txbuf_max;
218- (void ) sd_ble_tx_packet_count_get (conn_handle , &txbuf_max);
254+ (void ) sd_ble_tx_packet_count_get (conn_hdl , &txbuf_max);
219255 peer->hvn_tx_sem = xSemaphoreCreateCounting (txbuf_max, txbuf_max);
220256 #else
221- peer->hvn_tx_sem = xSemaphoreCreateCounting (getHvnQueueSize (conn_handle ), getHvnQueueSize (conn_handle ));
257+ peer->hvn_tx_sem = xSemaphoreCreateCounting (getHvnQueueSize (conn_hdl ), getHvnQueueSize (conn_hdl ));
222258 #endif
223259
224- peer->wrcmd_tx_sem = xSemaphoreCreateCounting (getWriteCmdQueueSize (conn_handle ), getWriteCmdQueueSize (conn_handle ));
260+ peer->wrcmd_tx_sem = xSemaphoreCreateCounting (getWriteCmdQueueSize (conn_hdl ), getWriteCmdQueueSize (conn_hdl ));
225261 }
226262 break ;
227263
@@ -230,7 +266,7 @@ void BLEGap::_eventHandler(ble_evt_t* evt)
230266 ble_gap_evt_disconnected_t const * para = &evt->evt .gap_evt .params .disconnected ;
231267
232268 // mark as disconnected, but keep the role for sub sequence event handler
233- peer->connected = false ;
269+ peer->connected = peer-> bonded = false ;
234270
235271 vSemaphoreDelete ( peer->hvn_tx_sem );
236272 peer->hvn_tx_sem = NULL ;
@@ -241,7 +277,115 @@ void BLEGap::_eventHandler(ble_evt_t* evt)
241277 break ;
242278
243279 case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
280+ {
244281 // Pairing in progress, Peer asking for our info
282+ peer->bond_data = (bond_data_t *) rtos_malloc ( sizeof (bond_data_t ));
283+ VERIFY (peer->bond_data , );
284+
285+ bond_data_t * bdata = peer->bond_data ;
286+ memclr (bdata, sizeof (bond_data_t ));
287+
288+ peer->ediv = 0xFFFF ; // invalid value for ediv
289+
290+ /* Step 1: Pairing/Bonding
291+ * - Central supplies its parameters
292+ * - We replies with our security parameters
293+ */
294+ // ble_gap_sec_params_t* peer = &evt->evt.gap_evt.params.sec_params_request.peer_params;
295+ COMMENT_OUT (
296+ // Change security parameter according to authentication type
297+ if ( _auth_type == BLE_GAP_AUTH_KEY_TYPE_PASSKEY)
298+ {
299+ sec_para.mitm = 1 ;
300+ sec_para.io_caps = BLE_GAP_IO_CAPS_DISPLAY_ONLY;
301+ }
302+ )
303+
304+ ble_gap_sec_keyset_t keyset =
305+ {
306+ .keys_own = {
307+ .p_enc_key = &bdata->own_enc ,
308+ .p_id_key = NULL ,
309+ .p_sign_key = NULL ,
310+ .p_pk = NULL
311+ },
312+
313+ .keys_peer = {
314+ .p_enc_key = &bdata->peer_enc ,
315+ .p_id_key = &bdata->peer_id ,
316+ .p_sign_key = NULL ,
317+ .p_pk = NULL
318+ }
319+ };
320+
321+ VERIFY_STATUS (sd_ble_gap_sec_params_reply (evt->evt .gap_evt .conn_handle , BLE_GAP_SEC_STATUS_SUCCESS, &_sec_param, &keyset), RETURN_VOID);
322+ }
323+ break ;
324+
325+ case BLE_GAP_EVT_AUTH_STATUS:
326+ {
327+ // Bonding process completed
328+ ble_gap_evt_auth_status_t * status = &evt->evt .gap_evt .params .auth_status ;
329+
330+ // Pairing/Bonding succeeded --> save encryption keys
331+ if (BLE_GAP_SEC_STATUS_SUCCESS == status->auth_status )
332+ {
333+ peer->bonded = true ;
334+ peer->ediv = peer->bond_data ->own_enc .master_id .ediv ;
335+
336+ bond_save_keys (conn_hdl, peer->bond_data );
337+ }else
338+ {
339+ PRINT_HEX (status->auth_status );
340+ }
341+
342+ rtos_free (peer->bond_data );
343+ peer->bond_data = NULL ;
344+ }
345+ break ;
346+
347+ case BLE_GAP_EVT_SEC_INFO_REQUEST:
348+ {
349+ // Reconnection. If bonded previously, Central will ask for stored keys.
350+ // return security information. Otherwise NULL
351+ ble_gap_evt_sec_info_request_t * sec_req = (ble_gap_evt_sec_info_request_t *) &evt->evt .gap_evt .params .sec_info_request ;
352+
353+ bond_data_t bdata;
354+ varclr (&bdata);
355+
356+ if ( bond_load_keys (sec_req->master_id .ediv , &bdata) )
357+ {
358+ sd_ble_gap_sec_info_reply (evt->evt .gap_evt .conn_handle , &bdata.own_enc .enc_info , &bdata.peer_id .id_info , NULL );
359+
360+ peer->ediv = bdata.own_enc .master_id .ediv ;
361+ } else
362+ {
363+ sd_ble_gap_sec_info_reply (evt->evt .gap_evt .conn_handle , NULL , NULL , NULL );
364+ }
365+ }
366+ break ;
367+
368+ case BLE_GAP_EVT_CONN_SEC_UPDATE:
369+ // Connection is secured aka Paired
370+
371+ // Previously bonded --> secure by re-connection process
372+ // --> Load & Set Sys Attr (Apply Service Context)
373+ // Else Init Sys Attr
374+ bond_load_cccd (conn_hdl, peer->ediv );
375+
376+ // Paired is Bonded (as we always save keys)
377+ peer->bonded = true ;
378+ break ;
379+
380+ case BLE_GAP_EVT_PASSKEY_DISPLAY:
381+ {
382+ // ble_gap_evt_passkey_display_t const* passkey_display = &evt->evt.gap_evt.params.passkey_display;
383+ //
384+ // PRINT_INT(passkey_display->match_request);
385+ // PRINT_BUFFER(passkey_display->passkey, 6);
386+
387+ // sd_ble_gap_auth_key_reply
388+ }
245389 break ;
246390
247391#if SD_VER < 500
@@ -283,7 +427,7 @@ void BLEGap::_eventHandler(ble_evt_t* evt)
283427 param->max_tx_octets , param->max_rx_octets , param->max_tx_time_us , param->max_rx_time_us );
284428
285429 // Let Softdevice decide the data length
286- VERIFY_STATUS ( sd_ble_gap_data_length_update (conn_handle , NULL , NULL ), );
430+ VERIFY_STATUS ( sd_ble_gap_data_length_update (conn_hdl , NULL , NULL ), );
287431 }
288432 break ;
289433
@@ -306,7 +450,7 @@ void BLEGap::_eventHandler(ble_evt_t* evt)
306450
307451 // Tell SoftDevice to choose PHY automatically
308452 ble_gap_phys_t phy = { BLE_GAP_PHY_AUTO, BLE_GAP_PHY_AUTO };
309- (void ) sd_ble_gap_phy_update (conn_handle , &phy);
453+ (void ) sd_ble_gap_phy_update (conn_hdl , &phy);
310454 }
311455 break ;
312456
@@ -329,8 +473,8 @@ void BLEGap::_eventHandler(ble_evt_t* evt)
329473
330474 case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
331475 {
332- peer->att_mtu = minof (evt->evt .gatts_evt .params .exchange_mtu_request .client_rx_mtu , getMaxMtu (conn_handle ));
333- VERIFY_STATUS ( sd_ble_gatts_exchange_mtu_reply (conn_handle , peer->att_mtu ), );
476+ peer->att_mtu = minof (evt->evt .gatts_evt .params .exchange_mtu_request .client_rx_mtu , getMaxMtu (conn_hdl ));
477+ VERIFY_STATUS ( sd_ble_gatts_exchange_mtu_reply (conn_hdl , peer->att_mtu ), );
334478
335479 LOG_LV1 (" GAP" , " ATT MTU is changed to %d" , peer->att_mtu );
336480 }
0 commit comments