mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-16 04:24:45 -07:00
Bluetooth timeout is now dynamic thanks to rssi analyzing
This commit is contained in:
@@ -38,14 +38,15 @@ typedef enum {
|
|||||||
LevelRssi59_40,
|
LevelRssi59_40,
|
||||||
LevelRssi39_0,
|
LevelRssi39_0,
|
||||||
LevelRssiNum,
|
LevelRssiNum,
|
||||||
} LevelRssiDelays;
|
LevelRssiError = 0xFF,
|
||||||
|
} LevelRssiRange;
|
||||||
|
|
||||||
const uint8_t bt_hid_delays[LevelRssiNum] = {
|
const uint8_t bt_hid_delays[LevelRssiNum] = {
|
||||||
45, // LevelRssi122_100
|
30, // LevelRssi122_100
|
||||||
41, // LevelRssi99_80
|
25, // LevelRssi99_80
|
||||||
37, // LevelRssi79_60
|
20, // LevelRssi79_60
|
||||||
33, // LevelRssi59_40
|
17, // LevelRssi59_40
|
||||||
30, // LevelRssi39_0
|
14, // LevelRssi39_0
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BadBleScript {
|
struct BadBleScript {
|
||||||
@@ -158,6 +159,37 @@ static const uint8_t numpad_keys[10] = {
|
|||||||
HID_KEYPAD_9,
|
HID_KEYPAD_9,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint8_t bt_timeout = 0;
|
||||||
|
|
||||||
|
static LevelRssiRange bt_remote_rssi_range(Bt *bt) {
|
||||||
|
|
||||||
|
BtRssi rssi_data = { 0 };
|
||||||
|
|
||||||
|
if (!bt_remote_rssi(bt, &rssi_data))
|
||||||
|
return LevelRssiError;
|
||||||
|
|
||||||
|
if (rssi_data.rssi <= 39)
|
||||||
|
return LevelRssi39_0;
|
||||||
|
else if (rssi_data.rssi <= 59)
|
||||||
|
return LevelRssi59_40;
|
||||||
|
else if (rssi_data.rssi <= 79)
|
||||||
|
return LevelRssi79_60;
|
||||||
|
else if (rssi_data.rssi <= 99)
|
||||||
|
return LevelRssi99_80;
|
||||||
|
else if (rssi_data.rssi <= 122)
|
||||||
|
return LevelRssi122_100;
|
||||||
|
|
||||||
|
return LevelRssiError;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void update_bt_timeout(Bt *bt) {
|
||||||
|
|
||||||
|
LevelRssiRange r = bt_remote_rssi_range(bt);
|
||||||
|
if (r < LevelRssiNum) {
|
||||||
|
bt_timeout = bt_hid_delays[r];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Wait until there are enough free slots in the keyboard buffer
|
* @brief Wait until there are enough free slots in the keyboard buffer
|
||||||
*
|
*
|
||||||
@@ -200,8 +232,8 @@ static void ducky_numlock_on() {
|
|||||||
if((furi_hal_hid_get_led_state() & HID_KB_LED_NUM) == 0) {
|
if((furi_hal_hid_get_led_state() & HID_KB_LED_NUM) == 0) {
|
||||||
bt_hid_hold_while_keyboard_buffer_full(1, -1);
|
bt_hid_hold_while_keyboard_buffer_full(1, -1);
|
||||||
furi_hal_bt_hid_kb_press(HID_KEYBOARD_LOCK_NUM_LOCK);
|
furi_hal_bt_hid_kb_press(HID_KEYBOARD_LOCK_NUM_LOCK);
|
||||||
FURI_LOG_I(WORKER_TAG, "BT RSSI: %f\r", (double)furi_hal_bt_get_rssi());
|
|
||||||
furi_delay_ms(25);
|
furi_delay_ms(bt_timeout);
|
||||||
furi_hal_bt_hid_kb_release(HID_KEYBOARD_LOCK_NUM_LOCK);
|
furi_hal_bt_hid_kb_release(HID_KEYBOARD_LOCK_NUM_LOCK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,10 +244,8 @@ static bool ducky_numpad_press(const char num) {
|
|||||||
uint16_t key = numpad_keys[num - '0'];
|
uint16_t key = numpad_keys[num - '0'];
|
||||||
bt_hid_hold_while_keyboard_buffer_full(1, -1);
|
bt_hid_hold_while_keyboard_buffer_full(1, -1);
|
||||||
FURI_LOG_I(WORKER_TAG, "Pressing %c\r\n", num);
|
FURI_LOG_I(WORKER_TAG, "Pressing %c\r\n", num);
|
||||||
|
|
||||||
furi_hal_bt_hid_kb_press(key);
|
furi_hal_bt_hid_kb_press(key);
|
||||||
FURI_LOG_I(WORKER_TAG, "BT RSSI: %f\r", (double)furi_hal_bt_get_rssi());
|
furi_delay_ms(bt_timeout);
|
||||||
furi_delay_ms(25);
|
|
||||||
furi_hal_bt_hid_kb_release(key);
|
furi_hal_bt_hid_kb_release(key);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -267,8 +297,8 @@ static bool ducky_string(BadBleScript* bad_ble, const char* param) {
|
|||||||
if(keycode != HID_KEYBOARD_NONE) {
|
if(keycode != HID_KEYBOARD_NONE) {
|
||||||
bt_hid_hold_while_keyboard_buffer_full(1, -1);
|
bt_hid_hold_while_keyboard_buffer_full(1, -1);
|
||||||
furi_hal_bt_hid_kb_press(keycode);
|
furi_hal_bt_hid_kb_press(keycode);
|
||||||
FURI_LOG_I(WORKER_TAG, "BT RSSI: %f\r", (double)furi_hal_bt_get_rssi());
|
|
||||||
furi_delay_ms(25);
|
furi_delay_ms(bt_timeout);
|
||||||
furi_hal_bt_hid_kb_release(keycode);
|
furi_hal_bt_hid_kb_release(keycode);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
@@ -377,8 +407,8 @@ static int32_t
|
|||||||
bt_hid_hold_while_keyboard_buffer_full(1, -1);
|
bt_hid_hold_while_keyboard_buffer_full(1, -1);
|
||||||
furi_hal_bt_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN);
|
furi_hal_bt_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN);
|
||||||
furi_hal_bt_hid_kb_press(key);
|
furi_hal_bt_hid_kb_press(key);
|
||||||
FURI_LOG_I(WORKER_TAG, "BT RSSI: %f\r", (double)furi_hal_bt_get_rssi());
|
|
||||||
furi_delay_ms(25);
|
furi_delay_ms(bt_timeout);
|
||||||
furi_hal_bt_hid_kb_release(key);
|
furi_hal_bt_hid_kb_release(key);
|
||||||
furi_hal_bt_hid_kb_release(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN);
|
furi_hal_bt_hid_kb_release(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN);
|
||||||
return (0);
|
return (0);
|
||||||
@@ -398,8 +428,8 @@ static int32_t
|
|||||||
}
|
}
|
||||||
FURI_LOG_I(WORKER_TAG, "Special key pressed %x\r\n", key);
|
FURI_LOG_I(WORKER_TAG, "Special key pressed %x\r\n", key);
|
||||||
furi_hal_bt_hid_kb_press(key);
|
furi_hal_bt_hid_kb_press(key);
|
||||||
FURI_LOG_I(WORKER_TAG, "BT RSSI: %f\r", (double)furi_hal_bt_get_rssi());
|
|
||||||
furi_delay_ms(25);
|
furi_delay_ms(bt_timeout);
|
||||||
furi_hal_bt_hid_kb_release(key);
|
furi_hal_bt_hid_kb_release(key);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -513,9 +543,13 @@ static void bad_ble_hid_state_callback(BtStatus status, void* context) {
|
|||||||
BadBleScript* bad_ble = (BadBleScript*)context;
|
BadBleScript* bad_ble = (BadBleScript*)context;
|
||||||
bool state = (status == BtStatusConnected);
|
bool state = (status == BtStatusConnected);
|
||||||
|
|
||||||
if(state == true)
|
if(state == true) {
|
||||||
|
LevelRssiRange r = bt_remote_rssi_range(bad_ble->bt);
|
||||||
|
if (r != LevelRssiError) {
|
||||||
|
bt_timeout = bt_hid_delays[r];
|
||||||
|
}
|
||||||
furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtConnect);
|
furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtConnect);
|
||||||
else
|
} else
|
||||||
furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtDisconnect);
|
furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtDisconnect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,6 +559,8 @@ static int32_t bad_ble_worker(void* context) {
|
|||||||
BadBleWorkerState worker_state = BadBleStateInit;
|
BadBleWorkerState worker_state = BadBleStateInit;
|
||||||
int32_t delay_val = 0;
|
int32_t delay_val = 0;
|
||||||
|
|
||||||
|
bt_timeout = bt_hid_delays[LevelRssi39_0];
|
||||||
|
|
||||||
// init ble hid
|
// init ble hid
|
||||||
bt_disconnect(bad_ble->bt);
|
bt_disconnect(bad_ble->bt);
|
||||||
|
|
||||||
@@ -625,6 +661,10 @@ static int32_t bad_ble_worker(void* context) {
|
|||||||
storage_file_seek(script_file, 0, true);
|
storage_file_seek(script_file, 0, true);
|
||||||
// extra time for PC to recognize Flipper as keyboard
|
// extra time for PC to recognize Flipper as keyboard
|
||||||
furi_thread_flags_wait(0, FuriFlagWaitAny, 1500);
|
furi_thread_flags_wait(0, FuriFlagWaitAny, 1500);
|
||||||
|
|
||||||
|
update_bt_timeout(bad_ble->bt);
|
||||||
|
FURI_LOG_I(WORKER_TAG, "BLE Key timeout : %u", bt_timeout);
|
||||||
|
|
||||||
worker_state = BadBleStateRunning;
|
worker_state = BadBleStateRunning;
|
||||||
} else if(flags & WorkerEvtToggle) { // Cancel scheduled execution
|
} else if(flags & WorkerEvtToggle) { // Cancel scheduled execution
|
||||||
worker_state = BadBleStateNotConnected;
|
worker_state = BadBleStateNotConnected;
|
||||||
@@ -685,6 +725,9 @@ static int32_t bad_ble_worker(void* context) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_bt_timeout(bad_ble->bt);
|
||||||
|
FURI_LOG_I(WORKER_TAG, "BLE Key timeout : %u", bt_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// release all keys
|
// release all keys
|
||||||
|
|||||||
@@ -30,30 +30,16 @@ void bad_ble_scene_error_on_enter(void* context) {
|
|||||||
app->widget, GuiButtonTypeLeft, "Back", bad_ble_scene_error_event_callback, app);
|
app->widget, GuiButtonTypeLeft, "Back", bad_ble_scene_error_event_callback, app);
|
||||||
} else if(app->error == BadBleAppErrorCloseRpc) {
|
} else if(app->error == BadBleAppErrorCloseRpc) {
|
||||||
widget_add_icon_element(app->widget, 78, 0, &I_ActiveConnection_50x64);
|
widget_add_icon_element(app->widget, 78, 0, &I_ActiveConnection_50x64);
|
||||||
if (settings->sfw_mode) {
|
widget_add_string_multiline_element(
|
||||||
widget_add_string_multiline_element(
|
app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Connection\nis active!");
|
||||||
app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Connection\nis active!");
|
widget_add_string_multiline_element(
|
||||||
widget_add_string_multiline_element(
|
app->widget,
|
||||||
app->widget,
|
3,
|
||||||
3,
|
30,
|
||||||
30,
|
AlignLeft,
|
||||||
AlignLeft,
|
AlignTop,
|
||||||
AlignTop,
|
FontSecondary,
|
||||||
FontSecondary,
|
"Disconnect from\nPC or phone to\nuse this function.");
|
||||||
"Disconnect from\nPC or phone to\nuse this function.");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
widget_add_string_multiline_element(
|
|
||||||
app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "I am not\na whore!");
|
|
||||||
widget_add_string_multiline_element(
|
|
||||||
app->widget,
|
|
||||||
3,
|
|
||||||
30,
|
|
||||||
AlignLeft,
|
|
||||||
AlignTop,
|
|
||||||
FontSecondary,
|
|
||||||
"Pull out from\nPC or phone to\nuse me like this.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(app->view_dispatcher, BadBleAppViewError);
|
view_dispatcher_switch_to_view(app->view_dispatcher, BadBleAppViewError);
|
||||||
|
|||||||
@@ -50,12 +50,7 @@ static void bad_ble_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
|
|
||||||
if((model->state.state == BadBleStateIdle) || (model->state.state == BadBleStateDone) ||
|
if((model->state.state == BadBleStateIdle) || (model->state.state == BadBleStateDone) ||
|
||||||
(model->state.state == BadBleStateNotConnected)) {
|
(model->state.state == BadBleStateNotConnected)) {
|
||||||
if (settings->sfw_mode) {
|
elements_button_center(canvas, "Start");
|
||||||
elements_button_center(canvas, "Start");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
elements_button_center(canvas, "Cum");
|
|
||||||
}
|
|
||||||
} else if((model->state.state == BadBleStateRunning) || (model->state.state == BadBleStateDelay)) {
|
} else if((model->state.state == BadBleStateRunning) || (model->state.state == BadBleStateDelay)) {
|
||||||
elements_button_center(canvas, "Stop");
|
elements_button_center(canvas, "Stop");
|
||||||
} else if(model->state.state == BadBleStateWillRun) {
|
} else if(model->state.state == BadBleStateWillRun) {
|
||||||
@@ -70,23 +65,12 @@ static void bad_ble_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
if(model->state.state == BadBleStateNotConnected) {
|
if(model->state.state == BadBleStateNotConnected) {
|
||||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||||
canvas_set_font(canvas, FontPrimary);
|
canvas_set_font(canvas, FontPrimary);
|
||||||
if (settings->sfw_mode) {
|
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect me");
|
||||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect me");
|
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to a computer");
|
||||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to a computer");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Plug me");
|
|
||||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "in, Daddy");
|
|
||||||
}
|
|
||||||
} else if(model->state.state == BadBleStateWillRun) {
|
} else if(model->state.state == BadBleStateWillRun) {
|
||||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||||
canvas_set_font(canvas, FontPrimary);
|
canvas_set_font(canvas, FontPrimary);
|
||||||
if (settings->sfw_mode) {
|
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run");
|
||||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will cum");
|
|
||||||
}
|
|
||||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect");
|
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect");
|
||||||
} else if(model->state.state == BadBleStateFileError) {
|
} else if(model->state.state == BadBleStateFileError) {
|
||||||
canvas_draw_icon(canvas, 4, 26, &I_Error_18x18);
|
canvas_draw_icon(canvas, 4, 26, &I_Error_18x18);
|
||||||
|
|||||||
@@ -428,6 +428,22 @@ const uint8_t *bt_get_profile_mac_address(Bt *bt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool bt_remote_rssi(Bt *bt, BtRssi *rssi) {
|
||||||
|
furi_assert(bt);
|
||||||
|
UNUSED(rssi);
|
||||||
|
|
||||||
|
uint8_t rssi_val;
|
||||||
|
uint32_t since = furi_hal_bt_get_conn_rssi(&rssi_val);
|
||||||
|
|
||||||
|
if (since == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rssi->rssi = rssi_val;
|
||||||
|
rssi->since = since;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t bt_srv(void* p) {
|
int32_t bt_srv(void* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
Bt* bt = bt_alloc();
|
Bt* bt = bt_alloc();
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ typedef enum {
|
|||||||
BtProfileHidKeyboard,
|
BtProfileHidKeyboard,
|
||||||
} BtProfile;
|
} BtProfile;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t rssi;
|
||||||
|
uint32_t since;
|
||||||
|
} BtRssi;
|
||||||
|
|
||||||
|
|
||||||
typedef void (*BtStatusChangedCallback)(BtStatus status, void* context);
|
typedef void (*BtStatusChangedCallback)(BtStatus status, void* context);
|
||||||
|
|
||||||
/** Change BLE Profile
|
/** Change BLE Profile
|
||||||
@@ -42,6 +48,8 @@ const char *bt_get_profile_adv_name(Bt *bt);
|
|||||||
void bt_set_profile_mac_address(Bt *bt, const uint8_t mac[6]);
|
void bt_set_profile_mac_address(Bt *bt, const uint8_t mac[6]);
|
||||||
const uint8_t *bt_get_profile_mac_address(Bt *bt);
|
const uint8_t *bt_get_profile_mac_address(Bt *bt);
|
||||||
|
|
||||||
|
bool bt_remote_rssi(Bt *bt, BtRssi *rssi);
|
||||||
|
|
||||||
|
|
||||||
/** Disconnect from Central
|
/** Disconnect from Central
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,v,12.7,,
|
Version,v,12.12,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
Header,+,applications/services/cli/cli_vcp.h,,
|
Header,+,applications/services/cli/cli_vcp.h,,
|
||||||
@@ -575,6 +575,7 @@ Function,?,bt_get_profile_adv_name,const char*,Bt*
|
|||||||
Function,?,bt_get_profile_mac_address,const uint8_t*,Bt*
|
Function,?,bt_get_profile_mac_address,const uint8_t*,Bt*
|
||||||
Function,+,bt_keys_storage_set_default_path,void,Bt*
|
Function,+,bt_keys_storage_set_default_path,void,Bt*
|
||||||
Function,+,bt_keys_storage_set_storage_path,void,"Bt*, const char*"
|
Function,+,bt_keys_storage_set_storage_path,void,"Bt*, const char*"
|
||||||
|
Function,?,bt_remote_rssi,_Bool,"Bt*, BtRssi*"
|
||||||
Function,?,bt_set_profile,_Bool,"Bt*, BtProfile"
|
Function,?,bt_set_profile,_Bool,"Bt*, BtProfile"
|
||||||
Function,?,bt_set_profile_adv_name,void,"Bt*, const char*, ..."
|
Function,?,bt_set_profile_adv_name,void,"Bt*, const char*, ..."
|
||||||
Function,?,bt_set_profile_mac_address,void,"Bt*, const uint8_t[6]"
|
Function,?,bt_set_profile_mac_address,void,"Bt*, const uint8_t[6]"
|
||||||
@@ -999,6 +1000,7 @@ Function,+,furi_hal_bt_change_app,_Bool,"FuriHalBtProfile, GapEventCallback, voi
|
|||||||
Function,+,furi_hal_bt_clear_white_list,_Bool,
|
Function,+,furi_hal_bt_clear_white_list,_Bool,
|
||||||
Function,+,furi_hal_bt_dump_state,void,FuriString*
|
Function,+,furi_hal_bt_dump_state,void,FuriString*
|
||||||
Function,+,furi_hal_bt_ensure_c2_mode,_Bool,BleGlueC2Mode
|
Function,+,furi_hal_bt_ensure_c2_mode,_Bool,BleGlueC2Mode
|
||||||
|
Function,?,furi_hal_bt_get_conn_rssi,uint32_t,uint8_t*
|
||||||
Function,+,furi_hal_bt_get_key_storage_buff,void,"uint8_t**, uint16_t*"
|
Function,+,furi_hal_bt_get_key_storage_buff,void,"uint8_t**, uint16_t*"
|
||||||
Function,?,furi_hal_bt_get_profile_adv_name,const char*,FuriHalBtProfile
|
Function,?,furi_hal_bt_get_profile_adv_name,const char*,FuriHalBtProfile
|
||||||
Function,?,furi_hal_bt_get_profile_mac_addr,const uint8_t*,FuriHalBtProfile
|
Function,?,furi_hal_bt_get_profile_mac_addr,const uint8_t*,FuriHalBtProfile
|
||||||
@@ -1035,7 +1037,7 @@ Function,+,furi_hal_bt_serial_start,void,
|
|||||||
Function,+,furi_hal_bt_serial_stop,void,
|
Function,+,furi_hal_bt_serial_stop,void,
|
||||||
Function,+,furi_hal_bt_serial_tx,_Bool,"uint8_t*, uint16_t"
|
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_key_storage_change_callback,void,"BleGlueKeyStorageChangedCallback, void*"
|
||||||
Function,?,furi_hal_bt_set_profile_adv_name,void,"FuriHalBtProfile, const char[( 1 + 8 + ( 8 + 1 ) )]"
|
Function,?,furi_hal_bt_set_profile_adv_name,void,"FuriHalBtProfile, const char[( 1 + ( 8 + 1 ) ) - 1]"
|
||||||
Function,?,furi_hal_bt_set_profile_mac_addr,void,"FuriHalBtProfile, const uint8_t[( 6 )]"
|
Function,?,furi_hal_bt_set_profile_mac_addr,void,"FuriHalBtProfile, const uint8_t[( 6 )]"
|
||||||
Function,+,furi_hal_bt_start_advertising,void,
|
Function,+,furi_hal_bt_start_advertising,void,
|
||||||
Function,+,furi_hal_bt_start_app,_Bool,"FuriHalBtProfile, GapEventCallback, void*"
|
Function,+,furi_hal_bt_start_app,_Bool,"FuriHalBtProfile, GapEventCallback, void*"
|
||||||
@@ -1578,6 +1580,7 @@ Function,-,gamma,double,double
|
|||||||
Function,-,gamma_r,double,"double, int*"
|
Function,-,gamma_r,double,"double, int*"
|
||||||
Function,-,gammaf,float,float
|
Function,-,gammaf,float,float
|
||||||
Function,-,gammaf_r,float,"float, int*"
|
Function,-,gammaf_r,float,"float, int*"
|
||||||
|
Function,?,gap_get_remote_conn_rssi,uint32_t,int8_t*
|
||||||
Function,-,gap_get_state,GapState,
|
Function,-,gap_get_state,GapState,
|
||||||
Function,-,gap_init,_Bool,"GapConfig*, GapEventCallback, void*"
|
Function,-,gap_init,_Bool,"GapConfig*, GapEventCallback, void*"
|
||||||
Function,-,gap_start_advertising,void,
|
Function,-,gap_start_advertising,void,
|
||||||
|
|||||||
|
@@ -27,6 +27,8 @@ typedef struct {
|
|||||||
GapConfig* config;
|
GapConfig* config;
|
||||||
GapConnectionParams connection_params;
|
GapConnectionParams connection_params;
|
||||||
GapState state;
|
GapState state;
|
||||||
|
int8_t conn_rssi;
|
||||||
|
uint32_t time_rssi_sample;
|
||||||
FuriMutex* state_mutex;
|
FuriMutex* state_mutex;
|
||||||
GapEventCallback on_event_cb;
|
GapEventCallback on_event_cb;
|
||||||
void* context;
|
void* context;
|
||||||
@@ -52,6 +54,16 @@ static const uint8_t gap_erk[16] =
|
|||||||
|
|
||||||
static Gap* gap = NULL;
|
static Gap* gap = NULL;
|
||||||
|
|
||||||
|
static inline void fetch_rssi() {
|
||||||
|
uint8_t ret_rssi = 127;
|
||||||
|
if (hci_read_rssi(gap->service.connection_handle, &ret_rssi) == BLE_STATUS_SUCCESS) {
|
||||||
|
gap->conn_rssi = (int8_t) ret_rssi;
|
||||||
|
gap->time_rssi_sample = furi_get_tick();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FURI_LOG_E(TAG, "Failed to read RSSI");
|
||||||
|
}
|
||||||
|
|
||||||
static void gap_advertise_start(GapState new_state);
|
static void gap_advertise_start(GapState new_state);
|
||||||
static int32_t gap_app(void* context);
|
static int32_t gap_app(void* context);
|
||||||
|
|
||||||
@@ -125,6 +137,9 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
|
|||||||
gap->connection_params.supervisor_timeout = event->Supervision_Timeout;
|
gap->connection_params.supervisor_timeout = event->Supervision_Timeout;
|
||||||
FURI_LOG_I(TAG, "Connection parameters event complete");
|
FURI_LOG_I(TAG, "Connection parameters event complete");
|
||||||
gap_verify_connection_parameters(gap);
|
gap_verify_connection_parameters(gap);
|
||||||
|
|
||||||
|
// save rssi for current connection
|
||||||
|
fetch_rssi();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,6 +166,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
|
|||||||
gap->connection_params.slave_latency = event->Conn_Latency;
|
gap->connection_params.slave_latency = event->Conn_Latency;
|
||||||
gap->connection_params.supervisor_timeout = event->Supervision_Timeout;
|
gap->connection_params.supervisor_timeout = event->Supervision_Timeout;
|
||||||
|
|
||||||
|
|
||||||
// Stop advertising as connection completed
|
// Stop advertising as connection completed
|
||||||
furi_timer_stop(gap->advertise_timer);
|
furi_timer_stop(gap->advertise_timer);
|
||||||
|
|
||||||
@@ -159,6 +175,9 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
|
|||||||
gap->service.connection_handle = event->Connection_Handle;
|
gap->service.connection_handle = event->Connection_Handle;
|
||||||
|
|
||||||
gap_verify_connection_parameters(gap);
|
gap_verify_connection_parameters(gap);
|
||||||
|
|
||||||
|
fetch_rssi();
|
||||||
|
|
||||||
// Start pairing by sending security request
|
// Start pairing by sending security request
|
||||||
aci_gap_slave_security_req(event->Connection_Handle);
|
aci_gap_slave_security_req(event->Connection_Handle);
|
||||||
} break;
|
} break;
|
||||||
@@ -243,6 +262,8 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
|
|||||||
pairing_complete->Status);
|
pairing_complete->Status);
|
||||||
aci_gap_terminate(gap->service.connection_handle, 5);
|
aci_gap_terminate(gap->service.connection_handle, 5);
|
||||||
} else {
|
} else {
|
||||||
|
fetch_rssi();
|
||||||
|
|
||||||
FURI_LOG_I(TAG, "Pairing complete");
|
FURI_LOG_I(TAG, "Pairing complete");
|
||||||
GapEvent event = {.type = GapEventTypeConnected};
|
GapEvent event = {.type = GapEventTypeConnected};
|
||||||
gap->on_event_cb(event, gap->context); //-V595
|
gap->on_event_cb(event, gap->context); //-V595
|
||||||
@@ -495,6 +516,9 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
|
|||||||
gap->service.connection_handle = 0xFFFF;
|
gap->service.connection_handle = 0xFFFF;
|
||||||
gap->enable_adv = true;
|
gap->enable_adv = true;
|
||||||
|
|
||||||
|
gap->conn_rssi = 127;
|
||||||
|
gap->time_rssi_sample = 0;
|
||||||
|
|
||||||
// Thread configuration
|
// Thread configuration
|
||||||
gap->thread = furi_thread_alloc_ex("BleGapDriver", 1024, gap_app, gap);
|
gap->thread = furi_thread_alloc_ex("BleGapDriver", 1024, gap_app, gap);
|
||||||
furi_thread_start(gap->thread);
|
furi_thread_start(gap->thread);
|
||||||
@@ -514,6 +538,19 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t gap_get_remote_conn_rssi(int8_t *rssi) {
|
||||||
|
if (gap && gap->state == GapStateConnected) {
|
||||||
|
fetch_rssi();
|
||||||
|
*rssi = gap->conn_rssi;
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "RSSI: %d", *rssi);
|
||||||
|
|
||||||
|
if (gap->time_rssi_sample)
|
||||||
|
return furi_get_tick() - gap->time_rssi_sample;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
GapState gap_get_state() {
|
GapState gap_get_state() {
|
||||||
GapState state;
|
GapState state;
|
||||||
if(gap) {
|
if(gap) {
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ GapState gap_get_state();
|
|||||||
|
|
||||||
void gap_thread_stop();
|
void gap_thread_stop();
|
||||||
|
|
||||||
|
uint32_t gap_get_remote_conn_rssi(int8_t *rssi);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -200,14 +200,14 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GapConfig* config = &profile_config[profile].config;
|
GapConfig* config = &profile_config[profile].config;
|
||||||
if (strlen(&(profile_config[profile].config.adv_name[1])) == 0) {
|
if(strlen(&(profile_config[profile].config.adv_name[1])) == 0) {
|
||||||
// Set advertise name
|
// Set advertise name
|
||||||
strlcpy(
|
strlcpy(
|
||||||
profile_config[profile].config.adv_name,
|
profile_config[profile].config.adv_name,
|
||||||
furi_hal_version_get_ble_local_device_name_ptr(),
|
furi_hal_version_get_ble_local_device_name_ptr(),
|
||||||
FURI_HAL_VERSION_DEVICE_NAME_LENGTH);
|
FURI_HAL_VERSION_DEVICE_NAME_LENGTH);
|
||||||
}
|
}
|
||||||
// Configure GAP
|
// Configure GAP
|
||||||
if(profile == FuriHalBtProfileSerial) {
|
if(profile == FuriHalBtProfileSerial) {
|
||||||
// Set mac address
|
// Set mac address
|
||||||
memcpy(
|
memcpy(
|
||||||
@@ -425,6 +425,23 @@ float furi_hal_bt_get_rssi() {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** fill the RSSI of the remote host of the bt connection and returns the time since
|
||||||
|
* the beginning of the connection
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint32_t furi_hal_bt_get_conn_rssi(uint8_t *rssi) {
|
||||||
|
|
||||||
|
int8_t ret_rssi = 0;
|
||||||
|
uint32_t since = gap_get_remote_conn_rssi(&ret_rssi);
|
||||||
|
|
||||||
|
if (ret_rssi == 127 || since == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*rssi = (uint8_t) abs(ret_rssi);
|
||||||
|
|
||||||
|
return since;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t furi_hal_bt_get_transmitted_packets() {
|
uint32_t furi_hal_bt_get_transmitted_packets() {
|
||||||
uint32_t packets = 0;
|
uint32_t packets = 0;
|
||||||
aci_hal_le_tx_test_packet_number(&packets);
|
aci_hal_le_tx_test_packet_number(&packets);
|
||||||
@@ -450,13 +467,14 @@ bool furi_hal_bt_ensure_c2_mode(BleGlueC2Mode mode) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_bt_set_profile_adv_name(FuriHalBtProfile profile, const char name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH]) {
|
void furi_hal_bt_set_profile_adv_name(
|
||||||
|
FuriHalBtProfile profile,
|
||||||
|
const char name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH-1]) {
|
||||||
furi_assert(profile < FuriHalBtProfileNumber);
|
furi_assert(profile < FuriHalBtProfileNumber);
|
||||||
furi_assert(name);
|
furi_assert(name);
|
||||||
|
|
||||||
memcpy(&(profile_config[profile].config.adv_name[1]),
|
memcpy(
|
||||||
name, FURI_HAL_VERSION_DEVICE_NAME_LENGTH);
|
&(profile_config[profile].config.adv_name[1]), name, FURI_HAL_VERSION_DEVICE_NAME_LENGTH-1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* furi_hal_bt_get_profile_adv_name(FuriHalBtProfile profile) {
|
const char* furi_hal_bt_get_profile_adv_name(FuriHalBtProfile profile) {
|
||||||
@@ -471,7 +489,6 @@ void furi_hal_bt_set_profile_mac_addr(
|
|||||||
furi_assert(mac_addr);
|
furi_assert(mac_addr);
|
||||||
|
|
||||||
memcpy(profile_config[profile].config.mac_address, mac_addr, GAP_MAC_ADDR_SIZE);
|
memcpy(profile_config[profile].config.mac_address, mac_addr, GAP_MAC_ADDR_SIZE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* furi_hal_bt_get_profile_mac_addr(FuriHalBtProfile profile) {
|
const uint8_t* furi_hal_bt_get_profile_mac_addr(FuriHalBtProfile profile) {
|
||||||
|
|||||||
@@ -224,14 +224,24 @@ uint32_t furi_hal_bt_get_transmitted_packets();
|
|||||||
*/
|
*/
|
||||||
bool furi_hal_bt_ensure_c2_mode(BleGlueC2Mode mode);
|
bool furi_hal_bt_ensure_c2_mode(BleGlueC2Mode mode);
|
||||||
|
|
||||||
void furi_hal_bt_set_profile_adv_name(FuriHalBtProfile profile, const char name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH]);
|
/** Modify profile advertisement name and restart bluetooth
|
||||||
|
* @param[in] profile profile type
|
||||||
|
* @param[in] name new adv name
|
||||||
|
*/
|
||||||
|
void furi_hal_bt_set_profile_adv_name(FuriHalBtProfile profile, const char name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH-1]);
|
||||||
|
|
||||||
const char *furi_hal_bt_get_profile_adv_name(FuriHalBtProfile profile);
|
const char *furi_hal_bt_get_profile_adv_name(FuriHalBtProfile profile);
|
||||||
|
|
||||||
|
/** Modify profile mac address and restart bluetooth
|
||||||
|
* @param[in] profile profile type
|
||||||
|
* @param[in] mac new mac address
|
||||||
|
*/
|
||||||
void furi_hal_bt_set_profile_mac_addr(FuriHalBtProfile profile, const uint8_t mac_addr[GAP_MAC_ADDR_SIZE]);
|
void furi_hal_bt_set_profile_mac_addr(FuriHalBtProfile profile, const uint8_t mac_addr[GAP_MAC_ADDR_SIZE]);
|
||||||
|
|
||||||
const uint8_t *furi_hal_bt_get_profile_mac_addr(FuriHalBtProfile profile);
|
const uint8_t *furi_hal_bt_get_profile_mac_addr(FuriHalBtProfile profile);
|
||||||
|
|
||||||
|
uint32_t furi_hal_bt_get_conn_rssi(uint8_t *rssi);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
3146
flipper.log
Normal file
3146
flipper.log
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user