FuriHal,BleGlue: prevent sleep while HCI command executed, proper bt api rpc locking. Fixes random system lockups. (#3107)
This commit is contained in:
		
							parent
							
								
									e1030e7999
								
							
						
					
					
						commit
						63d7d46bd3
					
				@ -359,13 +359,13 @@ static void bt_change_profile(Bt* bt, BtMessage* message) {
 | 
				
			|||||||
            *message->result = false;
 | 
					            *message->result = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT);
 | 
					    api_lock_unlock(message->lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void bt_close_connection(Bt* bt) {
 | 
					static void bt_close_connection(Bt* bt, BtMessage* message) {
 | 
				
			||||||
    bt_close_rpc_connection(bt);
 | 
					    bt_close_rpc_connection(bt);
 | 
				
			||||||
    furi_hal_bt_stop_advertising();
 | 
					    furi_hal_bt_stop_advertising();
 | 
				
			||||||
    furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT);
 | 
					    api_lock_unlock(message->lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int32_t bt_srv(void* p) {
 | 
					int32_t bt_srv(void* p) {
 | 
				
			||||||
@ -432,7 +432,7 @@ int32_t bt_srv(void* p) {
 | 
				
			|||||||
        } else if(message.type == BtMessageTypeSetProfile) {
 | 
					        } else if(message.type == BtMessageTypeSetProfile) {
 | 
				
			||||||
            bt_change_profile(bt, &message);
 | 
					            bt_change_profile(bt, &message);
 | 
				
			||||||
        } else if(message.type == BtMessageTypeDisconnect) {
 | 
					        } else if(message.type == BtMessageTypeDisconnect) {
 | 
				
			||||||
            bt_close_connection(bt);
 | 
					            bt_close_connection(bt, &message);
 | 
				
			||||||
        } else if(message.type == BtMessageTypeForgetBondedDevices) {
 | 
					        } else if(message.type == BtMessageTypeForgetBondedDevices) {
 | 
				
			||||||
            bt_keys_storage_delete(bt->keys_storage);
 | 
					            bt_keys_storage_delete(bt->keys_storage);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -6,11 +6,14 @@ bool bt_set_profile(Bt* bt, BtProfile profile) {
 | 
				
			|||||||
    // Send message
 | 
					    // Send message
 | 
				
			||||||
    bool result = false;
 | 
					    bool result = false;
 | 
				
			||||||
    BtMessage message = {
 | 
					    BtMessage message = {
 | 
				
			||||||
        .type = BtMessageTypeSetProfile, .data.profile = profile, .result = &result};
 | 
					        .lock = api_lock_alloc_locked(),
 | 
				
			||||||
 | 
					        .type = BtMessageTypeSetProfile,
 | 
				
			||||||
 | 
					        .data.profile = profile,
 | 
				
			||||||
 | 
					        .result = &result};
 | 
				
			||||||
    furi_check(
 | 
					    furi_check(
 | 
				
			||||||
        furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk);
 | 
					        furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk);
 | 
				
			||||||
    // Wait for unlock
 | 
					    // Wait for unlock
 | 
				
			||||||
    furi_event_flag_wait(bt->api_event, BT_API_UNLOCK_EVENT, FuriFlagWaitAny, FuriWaitForever);
 | 
					    api_lock_wait_unlock_and_free(message.lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -19,11 +22,11 @@ void bt_disconnect(Bt* bt) {
 | 
				
			|||||||
    furi_assert(bt);
 | 
					    furi_assert(bt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Send message
 | 
					    // Send message
 | 
				
			||||||
    BtMessage message = {.type = BtMessageTypeDisconnect};
 | 
					    BtMessage message = {.lock = api_lock_alloc_locked(), .type = BtMessageTypeDisconnect};
 | 
				
			||||||
    furi_check(
 | 
					    furi_check(
 | 
				
			||||||
        furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk);
 | 
					        furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk);
 | 
				
			||||||
    // Wait for unlock
 | 
					    // Wait for unlock
 | 
				
			||||||
    furi_event_flag_wait(bt->api_event, BT_API_UNLOCK_EVENT, FuriFlagWaitAny, FuriWaitForever);
 | 
					    api_lock_wait_unlock_and_free(message.lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void bt_set_status_changed_callback(Bt* bt, BtStatusChangedCallback callback, void* context) {
 | 
					void bt_set_status_changed_callback(Bt* bt, BtStatusChangedCallback callback, void* context) {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <furi.h>
 | 
					#include <furi.h>
 | 
				
			||||||
#include <furi_hal.h>
 | 
					#include <furi_hal.h>
 | 
				
			||||||
 | 
					#include <api_lock.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gui/gui.h>
 | 
					#include <gui/gui.h>
 | 
				
			||||||
#include <gui/view_port.h>
 | 
					#include <gui/view_port.h>
 | 
				
			||||||
@ -22,8 +23,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define BT_KEYS_STORAGE_PATH INT_PATH(BT_KEYS_STORAGE_FILE_NAME)
 | 
					#define BT_KEYS_STORAGE_PATH INT_PATH(BT_KEYS_STORAGE_FILE_NAME)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define BT_API_UNLOCK_EVENT (1UL << 0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    BtMessageTypeUpdateStatus,
 | 
					    BtMessageTypeUpdateStatus,
 | 
				
			||||||
    BtMessageTypeUpdateBatteryLevel,
 | 
					    BtMessageTypeUpdateBatteryLevel,
 | 
				
			||||||
@ -48,6 +47,7 @@ typedef union {
 | 
				
			|||||||
} BtMessageData;
 | 
					} BtMessageData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    FuriApiLock lock;
 | 
				
			||||||
    BtMessageType type;
 | 
					    BtMessageType type;
 | 
				
			||||||
    BtMessageData data;
 | 
					    BtMessageData data;
 | 
				
			||||||
    bool* result;
 | 
					    bool* result;
 | 
				
			||||||
 | 
				
			|||||||
@ -422,9 +422,7 @@ int32_t hid_ble_app(void* p) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    furi_record_close(RECORD_STORAGE);
 | 
					    furi_record_close(RECORD_STORAGE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(!bt_set_profile(app->bt, BtProfileHidKeyboard)) {
 | 
					    furi_check(bt_set_profile(app->bt, BtProfileHidKeyboard));
 | 
				
			||||||
        FURI_LOG_E(TAG, "Failed to switch to HID profile");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    furi_hal_bt_start_advertising();
 | 
					    furi_hal_bt_start_advertising();
 | 
				
			||||||
    bt_set_status_changed_callback(app->bt, bt_hid_connection_status_changed_callback, app);
 | 
					    bt_set_status_changed_callback(app->bt, bt_hid_connection_status_changed_callback, app);
 | 
				
			||||||
@ -442,9 +440,7 @@ int32_t hid_ble_app(void* p) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    bt_keys_storage_set_default_path(app->bt);
 | 
					    bt_keys_storage_set_default_path(app->bt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(!bt_set_profile(app->bt, BtProfileSerial)) {
 | 
					    furi_check(bt_set_profile(app->bt, BtProfileSerial));
 | 
				
			||||||
        FURI_LOG_E(TAG, "Failed to switch to Serial profile");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    hid_free(app);
 | 
					    hid_free(app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -181,9 +181,11 @@ static void ble_app_hci_event_handler(void* pPayload) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void ble_app_hci_status_not_handler(HCI_TL_CmdStatus_t status) {
 | 
					static void ble_app_hci_status_not_handler(HCI_TL_CmdStatus_t status) {
 | 
				
			||||||
    if(status == HCI_TL_CmdBusy) {
 | 
					    if(status == HCI_TL_CmdBusy) {
 | 
				
			||||||
 | 
					        furi_hal_power_insomnia_enter();
 | 
				
			||||||
        furi_mutex_acquire(ble_app->hci_mtx, FuriWaitForever);
 | 
					        furi_mutex_acquire(ble_app->hci_mtx, FuriWaitForever);
 | 
				
			||||||
    } else if(status == HCI_TL_CmdAvailable) {
 | 
					    } else if(status == HCI_TL_CmdAvailable) {
 | 
				
			||||||
        furi_mutex_release(ble_app->hci_mtx);
 | 
					        furi_mutex_release(ble_app->hci_mtx);
 | 
				
			||||||
 | 
					        furi_hal_power_insomnia_exit();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@
 | 
				
			|||||||
#include <hsem_map.h>
 | 
					#include <hsem_map.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <furi_hal_version.h>
 | 
					#include <furi_hal_version.h>
 | 
				
			||||||
 | 
					#include <furi_hal_power.h>
 | 
				
			||||||
#include <furi_hal_bt_hid.h>
 | 
					#include <furi_hal_bt_hid.h>
 | 
				
			||||||
#include <furi_hal_bt_serial.h>
 | 
					#include <furi_hal_bt_serial.h>
 | 
				
			||||||
#include <furi_hal_bus.c>
 | 
					#include <furi_hal_bus.c>
 | 
				
			||||||
@ -269,6 +270,7 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void furi_hal_bt_reinit() {
 | 
					void furi_hal_bt_reinit() {
 | 
				
			||||||
 | 
					    furi_hal_power_insomnia_enter();
 | 
				
			||||||
    FURI_LOG_I(TAG, "Disconnect and stop advertising");
 | 
					    FURI_LOG_I(TAG, "Disconnect and stop advertising");
 | 
				
			||||||
    furi_hal_bt_stop_advertising();
 | 
					    furi_hal_bt_stop_advertising();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -298,6 +300,7 @@ void furi_hal_bt_reinit() {
 | 
				
			|||||||
    furi_hal_bt_init();
 | 
					    furi_hal_bt_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    furi_hal_bt_start_radio_stack();
 | 
					    furi_hal_bt_start_radio_stack();
 | 
				
			||||||
 | 
					    furi_hal_power_insomnia_exit();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context) {
 | 
					bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user