diff --git a/applications/external/bad_bt/helpers/ducky_script.c b/applications/external/bad_bt/helpers/ducky_script.c index a59d377f2..96807f44d 100644 --- a/applications/external/bad_bt/helpers/ducky_script.c +++ b/applications/external/bad_bt/helpers/ducky_script.c @@ -64,10 +64,11 @@ static inline void update_bt_timeout(Bt* bt) { } typedef enum { - WorkerEvtToggle = (1 << 0), - WorkerEvtEnd = (1 << 1), - WorkerEvtConnect = (1 << 2), - WorkerEvtDisconnect = (1 << 3), + WorkerEvtStartStop = (1 << 0), + WorkerEvtPauseResume = (1 << 1), + WorkerEvtEnd = (1 << 2), + WorkerEvtConnect = (1 << 3), + WorkerEvtDisconnect = (1 << 4), } WorkerEvtFlags; static const char ducky_cmd_id[] = {"ID"}; @@ -280,6 +281,7 @@ static bool ducky_set_bt_id(BadBtScript* bad_bt, const char* line) { return false; } } + furi_hal_bt_reverse_mac_addr(mac); furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, line + mac_len); bt_set_profile_mac_address(bad_bt->bt, mac); @@ -498,24 +500,26 @@ static int32_t bad_bt_worker(void* context) { } else if(worker_state == BadBtStateNotConnected) { // State: Not connected uint32_t flags = bad_bt_flags_get( - WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever); + WorkerEvtEnd | WorkerEvtConnect | WorkerEvtDisconnect | WorkerEvtStartStop, + FuriWaitForever); if(flags & WorkerEvtEnd) { break; } else if(flags & WorkerEvtConnect) { worker_state = BadBtStateIdle; // Ready to run - } else if(flags & WorkerEvtToggle) { + } else if(flags & WorkerEvtStartStop) { worker_state = BadBtStateWillRun; // Will run when connected } bad_bt->st.state = worker_state; } else if(worker_state == BadBtStateIdle) { // State: ready to start uint32_t flags = bad_bt_flags_get( - WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriWaitForever); + WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtConnect | WorkerEvtDisconnect, + FuriWaitForever); if(flags & WorkerEvtEnd) { break; - } else if(flags & WorkerEvtToggle) { // Start executing script + } else if(flags & WorkerEvtStartStop) { // Start executing script delay_val = 0; bad_bt->buf_len = 0; bad_bt->st.line_cur = 0; @@ -534,7 +538,8 @@ static int32_t bad_bt_worker(void* context) { } else if(worker_state == BadBtStateWillRun) { // State: start on connection uint32_t flags = bad_bt_flags_get( - WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever); + WorkerEvtEnd | WorkerEvtConnect | WorkerEvtDisconnect | WorkerEvtStartStop, + FuriWaitForever); if(flags & WorkerEvtEnd) { break; @@ -549,21 +554,21 @@ static int32_t bad_bt_worker(void* context) { storage_file_seek(script_file, 0, true); // extra time for PC to recognize Flipper as keyboard flags = furi_thread_flags_wait( - WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtToggle, + WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtStartStop, FuriFlagWaitAny | FuriFlagNoClear, 1500); if(flags == (unsigned)FuriFlagErrorTimeout) { // If nothing happened - start script execution worker_state = BadBtStateRunning; - } else if(flags & WorkerEvtToggle) { + } else if(flags & WorkerEvtStartStop) { worker_state = BadBtStateIdle; - furi_thread_flags_clear(WorkerEvtToggle); + furi_thread_flags_clear(WorkerEvtStartStop); } update_bt_timeout(bad_bt->bt); bad_bt_script_set_keyboard_layout(bad_bt, bad_bt->keyboard_layout); - } else if(flags & WorkerEvtToggle) { // Cancel scheduled execution + } else if(flags & WorkerEvtStartStop) { // Cancel scheduled execution worker_state = BadBtStateNotConnected; } bad_bt->st.state = worker_state; @@ -571,13 +576,15 @@ static int32_t bad_bt_worker(void* context) { } else if(worker_state == BadBtStateRunning) { // State: running uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val); uint32_t flags = furi_thread_flags_wait( - WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur); + WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtConnect | WorkerEvtDisconnect, + FuriFlagWaitAny, + delay_cur); delay_val -= delay_cur; if(!(flags & FuriFlagError)) { if(flags & WorkerEvtEnd) { break; - } else if(flags & WorkerEvtToggle) { + } else if(flags & WorkerEvtStartStop) { worker_state = BadBtStateIdle; // Stop executing script furi_hal_bt_hid_kb_release_all(); @@ -630,11 +637,14 @@ static int32_t bad_bt_worker(void* context) { } else if(worker_state == BadBtStateWaitForBtn) { // State: Wait for button Press uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val); uint32_t flags = furi_thread_flags_wait( - WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur); + WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtConnect | + WorkerEvtDisconnect, + FuriFlagWaitAny, + delay_cur); if(!(flags & FuriFlagError)) { if(flags & WorkerEvtEnd) { break; - } else if(flags & WorkerEvtToggle) { + } else if(flags & WorkerEvtStartStop) { delay_val = 0; worker_state = BadBtStateRunning; } else if(flags & WorkerEvtDisconnect) { @@ -646,14 +656,15 @@ static int32_t bad_bt_worker(void* context) { } } else if(worker_state == BadBtStateStringDelay) { // State: print string with delays uint32_t flags = furi_thread_flags_wait( - WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, + WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtConnect | + WorkerEvtDisconnect, FuriFlagWaitAny, bad_bt->stringdelay); if(!(flags & FuriFlagError)) { if(flags & WorkerEvtEnd) { break; - } else if(flags & WorkerEvtToggle) { + } else if(flags & WorkerEvtStartStop) { worker_state = BadBtStateIdle; // Stop executing script furi_hal_bt_hid_kb_release_all(); @@ -768,7 +779,7 @@ void bad_bt_script_set_keyboard_layout(BadBtScript* bad_bt, FuriString* layout_p void bad_bt_script_toggle(BadBtScript* bad_bt) { furi_assert(bad_bt); - furi_thread_flags_set(furi_thread_get_id(bad_bt->thread), WorkerEvtToggle); + furi_thread_flags_set(furi_thread_get_id(bad_bt->thread), WorkerEvtStartStop); } BadBtState* bad_bt_script_get_state(BadBtScript* bad_bt) { diff --git a/applications/external/bad_bt/scenes/bad_bt_scene_config_mac.c b/applications/external/bad_bt/scenes/bad_bt_scene_config_mac.c index 47f63e08c..dcc783f0f 100644 --- a/applications/external/bad_bt/scenes/bad_bt_scene_config_mac.c +++ b/applications/external/bad_bt/scenes/bad_bt_scene_config_mac.c @@ -11,6 +11,8 @@ void bad_bt_scene_config_mac_byte_input_callback(void* context) { void bad_bt_scene_config_mac_on_enter(void* context) { BadBtApp* bad_bt = context; + furi_hal_bt_reverse_mac_addr(bad_bt->config.bt_mac); + // Setup view ByteInput* byte_input = bad_bt->byte_input; byte_input_set_header_text(byte_input, "Set BT MAC address"); @@ -30,7 +32,6 @@ bool bad_bt_scene_config_mac_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == BadBtAppCustomEventByteInputDone) { - bt_set_profile_mac_address(bad_bt->bt, bad_bt->config.bt_mac); scene_manager_previous_scene(bad_bt->scene_manager); consumed = true; } @@ -41,6 +42,10 @@ bool bad_bt_scene_config_mac_on_event(void* context, SceneManagerEvent event) { void bad_bt_scene_config_mac_on_exit(void* context) { BadBtApp* bad_bt = context; + furi_hal_bt_reverse_mac_addr(bad_bt->config.bt_mac); + + bt_set_profile_mac_address(bad_bt->bt, bad_bt->config.bt_mac); + // Clear view byte_input_set_result_callback(bad_bt->byte_input, NULL, NULL, NULL, NULL, 0); byte_input_set_header_text(bad_bt->byte_input, ""); diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index f8d7ef279..a636a757a 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1072,6 +1072,7 @@ Function,+,furi_hal_bt_lock_core2,void, Function,+,furi_hal_bt_nvm_sram_sem_acquire,void, Function,+,furi_hal_bt_nvm_sram_sem_release,void, Function,+,furi_hal_bt_reinit,void, +Function,+,furi_hal_bt_reverse_mac_addr,void,uint8_t[( 6 )] Function,+,furi_hal_bt_serial_notify_buffer_is_empty,void, Function,+,furi_hal_bt_serial_set_event_callback,void,"uint16_t, FuriHalBtSerialCallback, void*" Function,+,furi_hal_bt_serial_set_rpc_status,void,FuriHalBtSerialRpcStatus @@ -1079,7 +1080,7 @@ Function,+,furi_hal_bt_serial_start,void, Function,+,furi_hal_bt_serial_stop,void, Function,+,furi_hal_bt_serial_tx,_Bool,"uint8_t*, uint16_t" Function,+,furi_hal_bt_set_key_storage_change_callback,void,"BleGlueKeyStorageChangedCallback, void*" -Function,+,furi_hal_bt_set_profile_adv_name,void,"FuriHalBtProfile, const char[( 18 + 1 )]" +Function,+,furi_hal_bt_set_profile_adv_name,void,"FuriHalBtProfile, const char[( ( 1 + 8 + ( 8 + 1 ) ) + 1 )]" Function,+,furi_hal_bt_set_profile_mac_addr,void,"FuriHalBtProfile, const uint8_t[( 6 )]" Function,+,furi_hal_bt_set_profile_pairing_method,void,"FuriHalBtProfile, GapPairing" Function,+,furi_hal_bt_start_advertising,void, diff --git a/firmware/targets/f7/ble_glue/gap.h b/firmware/targets/f7/ble_glue/gap.h index 7b317e06c..396d64e67 100644 --- a/firmware/targets/f7/ble_glue/gap.h +++ b/firmware/targets/f7/ble_glue/gap.h @@ -67,7 +67,7 @@ typedef struct { bool bonding_mode; GapPairing pairing_method; uint8_t mac_address[GAP_MAC_ADDR_SIZE]; - char adv_name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH]; + char adv_name[FURI_HAL_BT_ADV_NAME_LENGTH]; GapConnectionParamsRequest conn_param; } GapConfig; diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index 2fc028d7c..5a150d388 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -14,9 +14,6 @@ #define TAG "FuriHalBt" -#define FURI_HAL_BT_DEFAULT_MAC_ADDR \ - { 0x6c, 0x7a, 0xd8, 0xac, 0x57, 0x72 } - /* Time, in ms, to wait for mode transition before crashing */ #define C2_MODE_SWITCH_TIMEOUT 10000 @@ -238,28 +235,29 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb, strlcpy( config->adv_name, furi_hal_version_get_ble_local_device_name_ptr(), - FURI_HAL_VERSION_DEVICE_NAME_LENGTH); + FURI_HAL_BT_ADV_NAME_LENGTH); config->adv_service_uuid |= furi_hal_version_get_hw_color(); } else if(profile == FuriHalBtProfileHidKeyboard) { // Change MAC address for HID profile - uint8_t default_mac[sizeof(config->mac_address)] = FURI_HAL_BT_DEFAULT_MAC_ADDR; const uint8_t* normal_mac = furi_hal_version_get_ble_mac(); - if(memcmp(config->mac_address, default_mac, sizeof(config->mac_address)) == 0) { + uint8_t empty_mac[sizeof(config->mac_address)] = FURI_HAL_BT_EMPTY_MAC_ADDR; + uint8_t default_mac[sizeof(config->mac_address)] = FURI_HAL_BT_DEFAULT_MAC_ADDR; + if(memcmp(config->mac_address, empty_mac, sizeof(config->mac_address)) == 0 || + memcmp(config->mac_address, normal_mac, sizeof(config->mac_address)) == 0 || + memcmp(config->mac_address, default_mac, sizeof(config->mac_address)) == 0) { memcpy(config->mac_address, normal_mac, sizeof(config->mac_address)); - } - if(memcmp(config->mac_address, normal_mac, sizeof(config->mac_address)) == 0) { config->mac_address[2]++; } // Change name Flipper -> Control - if(strnlen(config->adv_name, FURI_HAL_VERSION_DEVICE_NAME_LENGTH) < 2 || - strnlen(config->adv_name + 1, FURI_HAL_VERSION_DEVICE_NAME_LENGTH) < 1) { + if(strnlen(config->adv_name, FURI_HAL_BT_ADV_NAME_LENGTH) < 2 || + strnlen(config->adv_name + 1, FURI_HAL_BT_ADV_NAME_LENGTH - 1) < 1) { snprintf( config->adv_name, - FURI_HAL_VERSION_DEVICE_NAME_LENGTH, + FURI_HAL_BT_ADV_NAME_LENGTH, "%cControl %s", - *furi_hal_version_get_ble_local_device_name_ptr(), - furi_hal_version_get_ble_local_device_name_ptr() + 9); + AD_TYPE_COMPLETE_LOCAL_NAME, + furi_hal_version_get_name_ptr()); } } if(!gap_init(config, event_cb, context)) { @@ -485,6 +483,15 @@ uint32_t furi_hal_bt_get_conn_rssi(uint8_t* rssi) { return since; } +void furi_hal_bt_reverse_mac_addr(uint8_t mac_addr[GAP_MAC_ADDR_SIZE]) { + uint8_t tmp; + for(size_t i = 0; i < GAP_MAC_ADDR_SIZE / 2; i++) { + tmp = mac_addr[i]; + mac_addr[i] = mac_addr[GAP_MAC_ADDR_SIZE - 1 - i]; + mac_addr[GAP_MAC_ADDR_SIZE - 1 - i] = tmp; + } +} + void furi_hal_bt_set_profile_adv_name( FuriHalBtProfile profile, const char name[FURI_HAL_BT_ADV_NAME_LENGTH]) { @@ -492,13 +499,13 @@ void furi_hal_bt_set_profile_adv_name( furi_assert(name); if(strlen(name) == 0) { - memset( - &(profile_config[profile].config.adv_name[1]), - 0, - strlen(&(profile_config[profile].config.adv_name[1]))); + memset(&(profile_config[profile].config.adv_name[1]), 0, FURI_HAL_BT_ADV_NAME_LENGTH - 1); } else { profile_config[profile].config.adv_name[0] = AD_TYPE_COMPLETE_LOCAL_NAME; - memcpy(&(profile_config[profile].config.adv_name[1]), name, FURI_HAL_BT_ADV_NAME_LENGTH); + strlcpy( + &(profile_config[profile].config.adv_name[1]), + name, + FURI_HAL_BT_ADV_NAME_LENGTH - 1 /* BLE symbol */); } } diff --git a/firmware/targets/f7/furi_hal/furi_hal_version.c b/firmware/targets/f7/furi_hal/furi_hal_version.c index 0e5f428ba..b6460cc5f 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_version.c +++ b/firmware/targets/f7/furi_hal/furi_hal_version.c @@ -111,7 +111,11 @@ void furi_hal_version_set_name(const char* name) { } uint32_t company_id = LL_FLASH_GetSTCompanyID(); - uint32_t device_id = LL_FLASH_GetDeviceID(); + // uint32_t device_id = LL_FLASH_GetDeviceID(); + // Some flippers return 0x27 (flippers with chip revision 2003 6495) instead of 0x26 (flippers with chip revision 2001 6495) + // Mobile apps expects it to return 0x26 + // Hardcoded here temporarily until mobile apps is updated to handle 0x27 + uint32_t device_id = 0x26; furi_hal_version.ble_mac[0] = (uint8_t)(udn & 0x000000FF); furi_hal_version.ble_mac[1] = (uint8_t)((udn & 0x0000FF00) >> 8); furi_hal_version.ble_mac[2] = (uint8_t)((udn & 0x00FF0000) >> 16); diff --git a/firmware/targets/furi_hal_include/furi_hal_bt.h b/firmware/targets/furi_hal_include/furi_hal_bt.h index f128b1064..7354d8770 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt.h @@ -18,6 +18,12 @@ #define FURI_HAL_BT_STACK_VERSION_MINOR (12) #define FURI_HAL_BT_C2_START_TIMEOUT 1000 +#define FURI_HAL_BT_EMPTY_MAC_ADDR \ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + +#define FURI_HAL_BT_DEFAULT_MAC_ADDR \ + { 0x6c, 0x7a, 0xd8, 0xac, 0x57, 0x72 } + #ifdef __cplusplus extern "C" { #endif @@ -218,7 +224,12 @@ float furi_hal_bt_get_rssi(); */ uint32_t furi_hal_bt_get_transmitted_packets(); -// BadBT stuff +// BadBT Stuff +/** Reverse a MAC address byte order in-place + * @param[in] mac mac address to reverse +*/ +void furi_hal_bt_reverse_mac_addr(uint8_t mac_addr[GAP_MAC_ADDR_SIZE]); + /** Modify profile advertisement name and restart bluetooth * @param[in] profile profile type * @param[in] name new adv name diff --git a/firmware/targets/furi_hal_include/furi_hal_version.h b/firmware/targets/furi_hal_include/furi_hal_version.h index 4a3f4c170..351a7849b 100644 --- a/firmware/targets/furi_hal_include/furi_hal_version.h +++ b/firmware/targets/furi_hal_include/furi_hal_version.h @@ -16,9 +16,10 @@ extern "C" { #define FURI_HAL_VERSION_NAME_LENGTH 8 #define FURI_HAL_VERSION_ARRAY_NAME_LENGTH (FURI_HAL_VERSION_NAME_LENGTH + 1) -#define FURI_HAL_BT_ADV_NAME_LENGTH (18 + 1) // 18 characters + null terminator /** BLE symbol + "Flipper " + name */ #define FURI_HAL_VERSION_DEVICE_NAME_LENGTH (1 + 8 + FURI_HAL_VERSION_ARRAY_NAME_LENGTH) +// 18 characters + null terminator +#define FURI_HAL_BT_ADV_NAME_LENGTH (FURI_HAL_VERSION_DEVICE_NAME_LENGTH + 1) /** OTP Versions enum */ typedef enum {