5252#define BLE_ADV_AD_TYPE_FIELD_SIZE 1
5353#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1
5454
55+ static const ble_gap_sec_params_t pairing_sec_params = {
56+ .bond = 0 , // TODO: add bonding
57+ .mitm = 0 ,
58+ .lesc = 0 ,
59+ .keypress = 0 ,
60+ .oob = 0 ,
61+ .io_caps = BLE_GAP_IO_CAPS_NONE ,
62+ .min_key_size = 7 ,
63+ .max_key_size = 16 ,
64+ .kdist_own = { .enc = 1 , .id = 1 },
65+ .kdist_peer = { .enc = 1 , .id = 1 },
66+ };
67+
5568STATIC void check_data_fit (size_t data_len ) {
5669 if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX ) {
5770 mp_raise_ValueError (translate ("Data too large for advertisement packet" ));
@@ -61,6 +74,9 @@ STATIC void check_data_fit(size_t data_len) {
6174STATIC void peripheral_on_ble_evt (ble_evt_t * ble_evt , void * self_in ) {
6275 bleio_peripheral_obj_t * self = (bleio_peripheral_obj_t * )self_in ;
6376
77+ // For debugging.
78+ // mp_printf(&mp_plat_print, "Peripheral event: 0x%04x\n", ble_evt->header.evt_id);
79+
6480 switch (ble_evt -> header .evt_id ) {
6581 case BLE_GAP_EVT_CONNECTED : {
6682 // Central has connected.
@@ -89,10 +105,6 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
89105 // Someday may handle timeouts or limit reached.
90106 break ;
91107
92- case BLE_GAP_EVT_SEC_PARAMS_REQUEST :
93- sd_ble_gap_sec_params_reply (self -> conn_handle , BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP , NULL , NULL );
94- break ;
95-
96108 case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST : {
97109 ble_gap_evt_conn_param_update_request_t * request =
98110 & ble_evt -> evt .gap_evt .params .conn_param_update_request ;
@@ -113,6 +125,50 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
113125 sd_ble_gatts_sys_attr_set (self -> conn_handle , NULL , 0 , 0 );
114126 break ;
115127
128+ case BLE_GAP_EVT_SEC_PARAMS_REQUEST :
129+ sd_ble_gap_sec_params_reply (self -> conn_handle , BLE_GAP_SEC_STATUS_SUCCESS , & pairing_sec_params , NULL );
130+ break ;
131+
132+ case BLE_GAP_EVT_LESC_DHKEY_REQUEST :
133+ // TODO for LESC pairing:
134+ // sd_ble_gap_lesc_dhkey_reply(...);
135+ break ;
136+
137+ case BLE_GAP_EVT_AUTH_STATUS : {
138+ // Pairing process completed
139+ ble_gap_evt_auth_status_t * status = & ble_evt -> evt .gap_evt .params .auth_status ;
140+ if (BLE_GAP_SEC_STATUS_SUCCESS == status -> auth_status ) {
141+ mp_printf (& mp_plat_print , "Pairing succeeded, status: 0x%04x\n" , status -> auth_status );
142+ self -> pair_status = PAIR_PAIRED ;
143+ } else {
144+ mp_printf (& mp_plat_print , "Pairing failed, status: 0x%04x\n" , status -> auth_status );
145+ self -> pair_status = PAIR_NOT_PAIRED ;
146+ }
147+ break ;
148+ }
149+
150+ case BLE_GAP_EVT_CONN_SEC_UPDATE : {
151+ ble_gap_conn_sec_t * conn_sec = & ble_evt -> evt .gap_evt .params .conn_sec_update .conn_sec ;
152+ mp_printf (& mp_plat_print , "sm: %d, lv: %d\n" , conn_sec -> sec_mode .sm , conn_sec -> sec_mode .lv );
153+ if (conn_sec -> sec_mode .sm <= 1 && conn_sec -> sec_mode .lv <= 1 ) {
154+ // Security setup did not succeed:
155+ // mode 0, level 0 means no access
156+ // mode 1, level 1 means open link
157+ // mode >=1 and/or level >=1 means encryption is set up
158+ self -> pair_status = PAIR_NOT_PAIRED ;
159+ mp_printf (& mp_plat_print , "PAIR_NOT_PAIRED\n" );
160+ } else {
161+ // TODO: see Bluefruit lib
162+ // if ( !bond_load_cccd(_role, _conn_hdl, _ediv) ) {
163+ // sd_ble_gatts_sys_attr_set(_conn_hdl, NULL, 0, 0);
164+ // }
165+ self -> pair_status = PAIR_PAIRED ;
166+ mp_printf (& mp_plat_print , "PAIR_PAIRED\n" );
167+ }
168+ break ;
169+ }
170+
171+
116172 default :
117173 // For debugging.
118174 // mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id);
@@ -130,6 +186,7 @@ void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_
130186
131187 self -> conn_handle = BLE_CONN_HANDLE_INVALID ;
132188 self -> adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET ;
189+ self -> pair_status = PAIR_NOT_PAIRED ;
133190
134191 // Add all the services.
135192
@@ -157,7 +214,7 @@ void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_
157214}
158215
159216
160- mp_obj_list_t * common_hal_bleio_peripheral_get_services_list (bleio_peripheral_obj_t * self ) {
217+ mp_obj_list_t * common_hal_bleio_peripheral_get_services (bleio_peripheral_obj_t * self ) {
161218 return self -> services_list ;
162219}
163220
@@ -248,3 +305,25 @@ void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *self)
248305void common_hal_bleio_peripheral_disconnect (bleio_peripheral_obj_t * self ) {
249306 sd_ble_gap_disconnect (self -> conn_handle , BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION );
250307}
308+
309+ mp_obj_list_t * common_hal_bleio_peripheral_get_remote_services (bleio_peripheral_obj_t * self ) {
310+ return self -> remote_services_list ;
311+ }
312+
313+ void common_hal_bleio_peripheral_pair (bleio_peripheral_obj_t * self ) {
314+ self -> pair_status = PAIR_WAITING ;
315+
316+ uint32_t err_code = sd_ble_gap_authenticate (self -> conn_handle , & pairing_sec_params );
317+
318+ if (err_code != NRF_SUCCESS ) {
319+ mp_raise_OSError_msg_varg (translate ("Failed to start pairing, error 0x%04x" ), err_code );
320+ }
321+
322+ while (self -> pair_status == PAIR_WAITING ) {
323+ MICROPY_VM_HOOK_LOOP ;
324+ }
325+
326+ if (self -> pair_status == PAIR_NOT_PAIRED ) {
327+ mp_raise_OSError_msg (translate ("Failed to pair" ));
328+ }
329+ }
0 commit comments