[FL-2623] Add BLE disconnect request #1686
Co-authored-by: LionZXY <nikita@kulikof.ru> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									9ff29d12b2
								
							
						
					
					
						commit
						ead9f134f4
					
				| @ -165,6 +165,11 @@ static uint16_t bt_serial_event_callback(SerialServiceEvent event, void* context | |||||||
|         ret = rpc_session_get_available_size(bt->rpc_session); |         ret = rpc_session_get_available_size(bt->rpc_session); | ||||||
|     } else if(event.event == SerialServiceEventTypeDataSent) { |     } else if(event.event == SerialServiceEventTypeDataSent) { | ||||||
|         furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_BUFF_SENT); |         furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_BUFF_SENT); | ||||||
|  |     } else if(event.event == SerialServiceEventTypesBleResetRequest) { | ||||||
|  |         FURI_LOG_I(TAG, "BLE restart request received"); | ||||||
|  |         BtMessage message = {.type = BtMessageTypeSetProfile, .data.profile = BtProfileSerial}; | ||||||
|  |         furi_check( | ||||||
|  |             furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk); | ||||||
|     } |     } | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| @ -226,6 +231,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) { | |||||||
|                 rpc_session_set_context(bt->rpc_session, bt); |                 rpc_session_set_context(bt->rpc_session, bt); | ||||||
|                 furi_hal_bt_serial_set_event_callback( |                 furi_hal_bt_serial_set_event_callback( | ||||||
|                     RPC_BUFFER_SIZE, bt_serial_event_callback, bt); |                     RPC_BUFFER_SIZE, bt_serial_event_callback, bt); | ||||||
|  |                 furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatusActive); | ||||||
|             } else { |             } else { | ||||||
|                 FURI_LOG_W(TAG, "RPC is busy, failed to open new session"); |                 FURI_LOG_W(TAG, "RPC is busy, failed to open new session"); | ||||||
|             } |             } | ||||||
| @ -241,6 +247,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) { | |||||||
|     } else if(event.type == GapEventTypeDisconnected) { |     } else if(event.type == GapEventTypeDisconnected) { | ||||||
|         if(bt->profile == BtProfileSerial && bt->rpc_session) { |         if(bt->profile == BtProfileSerial && bt->rpc_session) { | ||||||
|             FURI_LOG_I(TAG, "Close RPC connection"); |             FURI_LOG_I(TAG, "Close RPC connection"); | ||||||
|  |             furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatusNotActive); | ||||||
|             furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_DISCONNECTED); |             furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_DISCONNECTED); | ||||||
|             rpc_session_close(bt->rpc_session); |             rpc_session_close(bt->rpc_session); | ||||||
|             furi_hal_bt_serial_set_event_callback(0, NULL, NULL); |             furi_hal_bt_serial_set_event_callback(0, NULL, NULL); | ||||||
| @ -330,14 +337,20 @@ static void bt_change_profile(Bt* bt, BtMessage* message) { | |||||||
|             } |             } | ||||||
|             furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt); |             furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt); | ||||||
|             bt->profile = message->data.profile; |             bt->profile = message->data.profile; | ||||||
|             *message->result = true; |             if(message->result) { | ||||||
|  |                 *message->result = true; | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|             FURI_LOG_E(TAG, "Failed to start Bt App"); |             FURI_LOG_E(TAG, "Failed to start Bt App"); | ||||||
|             *message->result = false; |             if(message->result) { | ||||||
|  |                 *message->result = false; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         bt_show_warning(bt, "Radio stack doesn't support this app"); |         bt_show_warning(bt, "Radio stack doesn't support this app"); | ||||||
|         *message->result = false; |         if(message->result) { | ||||||
|  |             *message->result = false; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT); |     furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT); | ||||||
| } | } | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ typedef struct { | |||||||
|     uint16_t rx_char_handle; |     uint16_t rx_char_handle; | ||||||
|     uint16_t tx_char_handle; |     uint16_t tx_char_handle; | ||||||
|     uint16_t flow_ctrl_char_handle; |     uint16_t flow_ctrl_char_handle; | ||||||
|  |     uint16_t rpc_status_char_handle; | ||||||
|     FuriMutex* buff_size_mtx; |     FuriMutex* buff_size_mtx; | ||||||
|     uint32_t buff_size; |     uint32_t buff_size; | ||||||
|     uint16_t bytes_ready_to_receive; |     uint16_t bytes_ready_to_receive; | ||||||
| @ -28,6 +29,8 @@ static const uint8_t char_rx_uuid[] = | |||||||
|     {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; |     {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; | ||||||
| static const uint8_t flow_ctrl_uuid[] = | static const uint8_t flow_ctrl_uuid[] = | ||||||
|     {0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; |     {0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; | ||||||
|  | static const uint8_t rpc_status_uuid[] = | ||||||
|  |     {0x00, 0x00, 0xfe, 0x64, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; | ||||||
| 
 | 
 | ||||||
| static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { | static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { | ||||||
|     SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck; |     SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck; | ||||||
| @ -67,6 +70,17 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { | |||||||
|                     furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk); |                     furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk); | ||||||
|                 } |                 } | ||||||
|                 ret = SVCCTL_EvtAckFlowEnable; |                 ret = SVCCTL_EvtAckFlowEnable; | ||||||
|  |             } else if(attribute_modified->Attr_Handle == serial_svc->rpc_status_char_handle + 1) { | ||||||
|  |                 SerialServiceRpcStatus* rpc_status = | ||||||
|  |                     (SerialServiceRpcStatus*)attribute_modified->Attr_Data; | ||||||
|  |                 if(*rpc_status == SerialServiceRpcStatusNotActive) { | ||||||
|  |                     if(serial_svc->callback) { | ||||||
|  |                         SerialServiceEvent event = { | ||||||
|  |                             .event = SerialServiceEventTypesBleResetRequest, | ||||||
|  |                         }; | ||||||
|  |                         serial_svc->callback(event, serial_svc->context); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) { |         } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) { | ||||||
|             FURI_LOG_T(TAG, "Ack received"); |             FURI_LOG_T(TAG, "Ack received"); | ||||||
| @ -82,6 +96,18 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void serial_svc_update_rpc_char(SerialServiceRpcStatus status) { | ||||||
|  |     tBleStatus ble_status = aci_gatt_update_char_value( | ||||||
|  |         serial_svc->svc_handle, | ||||||
|  |         serial_svc->rpc_status_char_handle, | ||||||
|  |         0, | ||||||
|  |         sizeof(SerialServiceRpcStatus), | ||||||
|  |         (uint8_t*)&status); | ||||||
|  |     if(ble_status) { | ||||||
|  |         FURI_LOG_E(TAG, "Failed to update RPC status char: %d", ble_status); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void serial_svc_start() { | void serial_svc_start() { | ||||||
|     tBleStatus status; |     tBleStatus status; | ||||||
|     serial_svc = malloc(sizeof(SerialSvc)); |     serial_svc = malloc(sizeof(SerialSvc)); | ||||||
| @ -90,7 +116,7 @@ void serial_svc_start() { | |||||||
| 
 | 
 | ||||||
|     // Add service
 |     // Add service
 | ||||||
|     status = aci_gatt_add_service( |     status = aci_gatt_add_service( | ||||||
|         UUID_TYPE_128, (Service_UUID_t*)service_uuid, PRIMARY_SERVICE, 10, &serial_svc->svc_handle); |         UUID_TYPE_128, (Service_UUID_t*)service_uuid, PRIMARY_SERVICE, 12, &serial_svc->svc_handle); | ||||||
|     if(status) { |     if(status) { | ||||||
|         FURI_LOG_E(TAG, "Failed to add Serial service: %d", status); |         FURI_LOG_E(TAG, "Failed to add Serial service: %d", status); | ||||||
|     } |     } | ||||||
| @ -141,6 +167,22 @@ void serial_svc_start() { | |||||||
|     if(status) { |     if(status) { | ||||||
|         FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status); |         FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status); | ||||||
|     } |     } | ||||||
|  |     // Add RPC status characteristic
 | ||||||
|  |     status = aci_gatt_add_char( | ||||||
|  |         serial_svc->svc_handle, | ||||||
|  |         UUID_TYPE_128, | ||||||
|  |         (const Char_UUID_t*)rpc_status_uuid, | ||||||
|  |         sizeof(SerialServiceRpcStatus), | ||||||
|  |         CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_NOTIFY, | ||||||
|  |         ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, | ||||||
|  |         GATT_NOTIFY_ATTRIBUTE_WRITE, | ||||||
|  |         10, | ||||||
|  |         CHAR_VALUE_LEN_CONSTANT, | ||||||
|  |         &serial_svc->rpc_status_char_handle); | ||||||
|  |     if(status) { | ||||||
|  |         FURI_LOG_E(TAG, "Failed to add RPC status characteristic: %d", status); | ||||||
|  |     } | ||||||
|  |     serial_svc_update_rpc_char(SerialServiceRpcStatusNotActive); | ||||||
|     // Allocate buffer size mutex
 |     // Allocate buffer size mutex
 | ||||||
|     serial_svc->buff_size_mtx = furi_mutex_alloc(FuriMutexTypeNormal); |     serial_svc->buff_size_mtx = furi_mutex_alloc(FuriMutexTypeNormal); | ||||||
| } | } | ||||||
| @ -198,6 +240,10 @@ void serial_svc_stop() { | |||||||
|         if(status) { |         if(status) { | ||||||
|             FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status); |             FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status); | ||||||
|         } |         } | ||||||
|  |         status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rpc_status_char_handle); | ||||||
|  |         if(status) { | ||||||
|  |             FURI_LOG_E(TAG, "Failed to delete RPC Status characteristic: %d", status); | ||||||
|  |         } | ||||||
|         // Delete service
 |         // Delete service
 | ||||||
|         status = aci_gatt_del_service(serial_svc->svc_handle); |         status = aci_gatt_del_service(serial_svc->svc_handle); | ||||||
|         if(status) { |         if(status) { | ||||||
| @ -242,3 +288,8 @@ bool serial_svc_update_tx(uint8_t* data, uint16_t data_len) { | |||||||
| 
 | 
 | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void serial_svc_set_rpc_status(SerialServiceRpcStatus status) { | ||||||
|  |     furi_assert(serial_svc); | ||||||
|  |     serial_svc_update_rpc_char(status); | ||||||
|  | } | ||||||
|  | |||||||
| @ -10,9 +10,15 @@ | |||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | typedef enum { | ||||||
|  |     SerialServiceRpcStatusNotActive = 0UL, | ||||||
|  |     SerialServiceRpcStatusActive = 1UL, | ||||||
|  | } SerialServiceRpcStatus; | ||||||
|  | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     SerialServiceEventTypeDataReceived, |     SerialServiceEventTypeDataReceived, | ||||||
|     SerialServiceEventTypeDataSent, |     SerialServiceEventTypeDataSent, | ||||||
|  |     SerialServiceEventTypesBleResetRequest, | ||||||
| } SerialServiceEventType; | } SerialServiceEventType; | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
| @ -34,6 +40,8 @@ void serial_svc_set_callbacks( | |||||||
|     SerialServiceEventCallback callback, |     SerialServiceEventCallback callback, | ||||||
|     void* context); |     void* context); | ||||||
| 
 | 
 | ||||||
|  | void serial_svc_set_rpc_status(SerialServiceRpcStatus status); | ||||||
|  | 
 | ||||||
| void serial_svc_notify_buffer_is_empty(); | void serial_svc_notify_buffer_is_empty(); | ||||||
| 
 | 
 | ||||||
| void serial_svc_stop(); | void serial_svc_stop(); | ||||||
|  | |||||||
| @ -31,6 +31,16 @@ void furi_hal_bt_serial_notify_buffer_is_empty() { | |||||||
|     serial_svc_notify_buffer_is_empty(); |     serial_svc_notify_buffer_is_empty(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatus status) { | ||||||
|  |     SerialServiceRpcStatus st; | ||||||
|  |     if(status == FuriHalBtSerialRpcStatusActive) { | ||||||
|  |         st = SerialServiceRpcStatusActive; | ||||||
|  |     } else { | ||||||
|  |         st = SerialServiceRpcStatusNotActive; | ||||||
|  |     } | ||||||
|  |     serial_svc_set_rpc_status(st); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool furi_hal_bt_serial_tx(uint8_t* data, uint16_t size) { | bool furi_hal_bt_serial_tx(uint8_t* data, uint16_t size) { | ||||||
|     if(size > FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX) { |     if(size > FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX) { | ||||||
|         return false; |         return false; | ||||||
|  | |||||||
| @ -8,6 +8,11 @@ extern "C" { | |||||||
| 
 | 
 | ||||||
| #define FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX SERIAL_SVC_DATA_LEN_MAX | #define FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX SERIAL_SVC_DATA_LEN_MAX | ||||||
| 
 | 
 | ||||||
|  | typedef enum { | ||||||
|  |     FuriHalBtSerialRpcStatusNotActive, | ||||||
|  |     FuriHalBtSerialRpcStatusActive, | ||||||
|  | } FuriHalBtSerialRpcStatus; | ||||||
|  | 
 | ||||||
| /** Serial service callback type */ | /** Serial service callback type */ | ||||||
| typedef SerialServiceEventCallback FuriHalBtSerialCallback; | typedef SerialServiceEventCallback FuriHalBtSerialCallback; | ||||||
| 
 | 
 | ||||||
| @ -30,6 +35,12 @@ void furi_hal_bt_serial_set_event_callback( | |||||||
|     FuriHalBtSerialCallback callback, |     FuriHalBtSerialCallback callback, | ||||||
|     void* context); |     void* context); | ||||||
| 
 | 
 | ||||||
|  | /** Set BLE RPC status
 | ||||||
|  |  * | ||||||
|  |  * @param status        FuriHalBtSerialRpcStatus instance | ||||||
|  |  */ | ||||||
|  | void furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatus status); | ||||||
|  | 
 | ||||||
| /** Notify that application buffer is empty
 | /** Notify that application buffer is empty
 | ||||||
|  */ |  */ | ||||||
| void furi_hal_bt_serial_notify_buffer_is_empty(); | void furi_hal_bt_serial_notify_buffer_is_empty(); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich