diff --git a/app/ble/ble_service.c b/app/ble/ble_service.c index 04838a3..8b66650 100644 --- a/app/ble/ble_service.c +++ b/app/ble/ble_service.c @@ -17,6 +17,7 @@ static uint32_t _pairing_passkey = 0; /* Connection handle to the connected device : only one simultaneous connection */ static uint16_t ble_device_conn_handle = BLE_HS_CONN_HANDLE_NONE; static uint16_t usable_mtu = USABLE_DEFAULT_MTU; +static uint8_t _device_mac_address[6] = {0x00}; /** * @brief Structure used to store the various data to carry out a chunked notification or indication data transfer @@ -31,7 +32,8 @@ typedef struct bool transfer_in_progress; // Is a transfer already in progress ? } data_being_sent_t; -// Only one transfer of a type () can occur at any given time +// Only one transfer of a type can occur at any given time ie +// one notification and one indication can happen at the same time but not more. static data_being_sent_t notification_data = {.data = NULL, .length = 0, .offset = 0, .transfer_in_progress = false}; static data_being_sent_t indication_data = {.data = NULL, .length = 0, .offset = 0, .transfer_in_progress = false}; @@ -284,6 +286,28 @@ bool ble_service_is_device_connected(void) return _ble_service_state == BLE_SERVICE_MODE_CONNECTED; } +const uint8_t *ble_service_get_device_mac_address(void) +{ + // We only need to read from efuse section once. + if( + _device_mac_address[0] == 0 && + _device_mac_address[1] == 0 && + _device_mac_address[2] == 0 && + _device_mac_address[3] == 0 && + _device_mac_address[4] == 0 && + _device_mac_address[5] == 0 + ) + { + extern int tls_get_bt_mac_addr(u8 *mac); + tls_get_bt_mac_addr(_device_mac_address); + + // Make sure the device address is compliant with the random address specification : + _device_mac_address[5] |= 0xC0; + } + + return _device_mac_address; +} + void ble_service_register_state_change_cb(ble_service_state_change_fn_t ble_service_state_change_cb) { _ble_service_state_change_cb = ble_service_state_change_cb; @@ -299,6 +323,11 @@ void ble_service_set_pairing_passkey(uint32_t passkey) _pairing_passkey = passkey; } +uint32_t ble_service_get_active_pairing_passkey(void) +{ + return _pairing_passkey; +} + bool ble_service_update_connection_parameters( uint16_t itvl_min, uint16_t itvl_max, @@ -323,7 +352,7 @@ bool ble_service_update_connection_parameters( gap_params_to_apply.min_ce_len = min_ce_len; gap_params_to_apply.max_ce_len = max_ce_len; - if ((status = ble_gap_update_params(ble_device_conn_handle, &gap_params_to_apply)) != BLE_HS_ENOERR) + if((status = ble_gap_update_params(ble_device_conn_handle, &gap_params_to_apply)) != BLE_HS_ENOERR) { TLS_BT_APPL_TRACE_ERROR("%s, ble_gap_update_params failed %s" NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status)); return false; @@ -360,6 +389,8 @@ bool ble_service_send_nus_data(const uint8_t *data, uint16_t length) return false; } + if(ble_modem_is_sleeping())ble_modem_wake(); + notification_data.transfer_in_progress = true; notification_data.data = data; notification_data.length = length; @@ -488,15 +519,9 @@ static bool ble_service_advertise(bool enable) advertisement_fields.appearance = ble_svc_gap_device_appearance(); advertisement_fields.appearance_is_present = 1; - // Set the name of a watch supported by GB - #ifdef GADGETBRIDGE_SUPPORT - static const char dev_name[12] = "Bangle.js 2"; - advertisement_fields.name = (uint8_t *)dev_name;//ble_svc_gap_device_name(); - advertisement_fields.name_len = 11;//strlen(ble_svc_gap_device_name()); - #else + // Set the name of the BLE device advertisement_fields.name = (uint8_t *)ble_svc_gap_device_name(); advertisement_fields.name_len = strlen(ble_svc_gap_device_name()); - #endif advertisement_fields.name_is_complete = 1; @@ -514,15 +539,10 @@ static bool ble_service_advertise(bool enable) return false; } - // We the device address - uint8_t device_addr[6] = {0}; - extern int tls_get_bt_mac_addr(u8 *mac); - tls_get_bt_mac_addr(device_addr); + // We set the device address + const uint8_t *device_mac_address = ble_service_get_device_mac_address(); - // Make sure the the device address is compliant with the random address specification : - device_addr[5] |= 0xC0; - - if((status = ble_hs_id_set_rnd(device_addr)) != BLE_HS_ENOERR) + if((status = ble_hs_id_set_rnd(device_mac_address)) != BLE_HS_ENOERR) { TLS_BT_APPL_TRACE_ERROR("%s, ble_hs_id_set_rnd failed : %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status)); return false; @@ -531,12 +551,12 @@ static bool ble_service_advertise(bool enable) { TLS_BT_APPL_TRACE_VERBOSE("addr type : %s"NEW_LINE"device addr : %02X:%02X:%02X:%02X:%02X:%02X"NEW_LINE, tls_bt_addr_type_2_str(own_addr_type), - device_addr[5], - device_addr[4], - device_addr[3], - device_addr[2], - device_addr[1], - device_addr[0]); + device_mac_address[5], + device_mac_address[4], + device_mac_address[3], + device_mac_address[2], + device_mac_address[1], + device_mac_address[0]); } // We are now ready to configure the advertisement parameters @@ -593,6 +613,8 @@ static int ble_gap_event_cb(struct ble_gap_event *event, void *arg) usable_mtu = USABLE_DEFAULT_MTU; ble_device_conn_handle = event->connect.conn_handle; + // We register an event callback on the connection, + // this allows to be notified on the passkey action event if((status = ble_gap_set_event_cb(event->connect.conn_handle, &(ble_conn_gap_event_cb), NULL)) != BLE_HS_ENOERR) { TLS_BT_APPL_TRACE_WARNING("%s, ble_gap_set_event_cb %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status)); @@ -600,7 +622,7 @@ static int ble_gap_event_cb(struct ble_gap_event *event, void *arg) //We call the state change callback if registered if(_ble_service_state_change_cb)_ble_service_state_change_cb(_ble_service_state); - tls_bt_ctrl_sleep(false); + if(ble_modem_is_sleeping())ble_modem_wake(); } else { @@ -691,6 +713,20 @@ static int ble_gap_event_cb(struct ble_gap_event *event, void *arg) event->subscribe.cur_notify, event->subscribe.prev_notify ); + + if(gatt_nus_char_tx_handle == event->subscribe.attr_handle) + { + if(event->subscribe.cur_notify || event->subscribe.cur_indicate) + { + //We call the state change callback if registered + if(_ble_service_state_change_cb)_ble_service_state_change_cb(BLE_SERVICE_MODE_SUBSCRIBED); + } + else if(!event->subscribe.cur_notify && !event->subscribe.cur_indicate) + { + //We call the state change callback if registered + if(_ble_service_state_change_cb)_ble_service_state_change_cb(BLE_SERVICE_MODE_UNSUBSCRIBED); + } + } break; case BLE_GAP_EVENT_MTU: TLS_BT_APPL_TRACE_VERBOSE("MTU update : %u"NEW_LINE, event->mtu.value); @@ -729,6 +765,7 @@ static int ble_gap_event_cb(struct ble_gap_event *event, void *arg) TLS_BT_APPL_TRACE_VERBOSE("last data chunk sent, end of the transfer"NEW_LINE); // All data have been sent, end of the transfer reset_data_being_sent(¬ification_data); + if(!ble_modem_is_sleeping())ble_modem_sleep(); } } else // Indication diff --git a/app/ble/ble_service.h b/app/ble/ble_service.h index 3d9c758..df12d16 100644 --- a/app/ble/ble_service.h +++ b/app/ble/ble_service.h @@ -15,6 +15,8 @@ typedef enum BLE_SERVICE_MODE_IDLE, BLE_SERVICE_MODE_ADVERTISING, BLE_SERVICE_MODE_CONNECTED, + BLE_SERVICE_MODE_SUBSCRIBED, + BLE_SERVICE_MODE_UNSUBSCRIBED, BLE_SERVICE_MODE_INDICATING, BLE_SERVICE_MODE_EXITING } ble_service_state_e; @@ -61,6 +63,13 @@ bool ble_service_is_started(void); */ bool ble_service_is_device_connected(void); +/** + * @brief Returns the MAC address of the BLE device. + * + * @return a pointer to a constant array of size 6 containing the address. + */ +const uint8_t *ble_service_get_device_mac_address(void); + /** * @brief Registers a callback function called every time the state of the BLE service changes. * For example, you can register a callback to know if a device connected to the service, or disconnected @@ -70,19 +79,27 @@ bool ble_service_is_device_connected(void); void ble_service_register_state_change_cb(ble_service_state_change_fn_t ble_service_state_change_cb); /** - * @brief Returns the current state of the ble service + * @brief Returns the current state of the ble service. * - * @return ble_service_state_e + * @return ble_service_state_e enum value */ ble_service_state_e ble_service_get_state(void); /** - * @brief + * @brief Sets the passkey which is asked by the phone when trying to pair the device for the first time. * - * @param passkey + * @param passkey the passkey to set, might be mandatory to be a 6 digit number. */ void ble_service_set_pairing_passkey(uint32_t passkey); +/** + * @brief Returns the passkey needed for pairing which was previously set by the @ref ble_service_set_pairing_passkey + * function. + * + * @return uint32_t the number representing the passkey. + */ +uint32_t ble_service_get_active_pairing_passkey(void); + /** * @brief Asks to update the current connection parameters * /!\ A connection should be already active before calling this function.