Bad BT plugin, Submenu locked elements, API updates, etc.

Thanks to WillyJL, ClaraCrazy, and XFW contributors
This commit is contained in:
MX
2023-05-13 00:14:22 +03:00
parent a7691b2d3b
commit 849f14e480
42 changed files with 3211 additions and 44 deletions
+22
View File
@@ -586,11 +586,20 @@ Function,+,ble_glue_start,_Bool,
Function,+,ble_glue_thread_stop,void,
Function,+,ble_glue_wait_for_c2_start,_Bool,int32_t
Function,-,bsearch,void*,"const void*, const void*, size_t, size_t, __compar_fn_t"
Function,+,bt_disable_peer_key_update,void,Bt*
Function,+,bt_disconnect,void,Bt*
Function,+,bt_enable_peer_key_update,void,Bt*
Function,+,bt_forget_bonded_devices,void,Bt*
Function,+,bt_get_profile_adv_name,const char*,Bt*
Function,+,bt_get_profile_mac_address,const uint8_t*,Bt*
Function,+,bt_get_profile_pairing_method,GapPairing,Bt*
Function,+,bt_keys_storage_set_default_path,void,Bt*
Function,+,bt_keys_storage_set_storage_path,void,"Bt*, const char*"
Function,+,bt_remote_rssi,_Bool,"Bt*, uint8_t*"
Function,+,bt_set_profile,_Bool,"Bt*, BtProfile"
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_pairing_method,void,"Bt*, GapPairing"
Function,+,bt_set_status_changed_callback,void,"Bt*, BtStatusChangedCallback, void*"
Function,+,buffered_file_stream_alloc,Stream*,Storage*
Function,+,buffered_file_stream_close,_Bool,Stream*
@@ -816,6 +825,7 @@ Function,+,elements_multiline_text_framed,void,"Canvas*, uint8_t, uint8_t, const
Function,+,elements_progress_bar,void,"Canvas*, uint8_t, uint8_t, uint8_t, float"
Function,+,elements_progress_bar_with_text,void,"Canvas*, uint8_t, uint8_t, uint8_t, float, const char*"
Function,+,elements_scrollable_text_line,void,"Canvas*, uint8_t, uint8_t, uint8_t, FuriString*, size_t, _Bool"
Function,+,elements_scrollable_text_line_str,void,"Canvas*, uint8_t, uint8_t, uint8_t, const char*, size_t, _Bool, _Bool"
Function,+,elements_scrollbar,void,"Canvas*, uint16_t, uint16_t"
Function,+,elements_scrollbar_pos,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t"
Function,+,elements_slightly_rounded_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t"
@@ -1037,14 +1047,19 @@ Function,+,furi_hal_bt_change_app,_Bool,"FuriHalBtProfile, GapEventCallback, voi
Function,+,furi_hal_bt_clear_white_list,_Bool,
Function,+,furi_hal_bt_dump_state,void,FuriString*
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_hardfault_info,const FuriHalBtHardfaultInfo*,
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_mac_addr,const uint8_t*,FuriHalBtProfile
Function,+,furi_hal_bt_get_profile_pairing_method,GapPairing,FuriHalBtProfile
Function,+,furi_hal_bt_get_radio_stack,FuriHalBtStack,
Function,+,furi_hal_bt_get_rssi,float,
Function,+,furi_hal_bt_get_transmitted_packets,uint32_t,
Function,+,furi_hal_bt_hid_consumer_key_press,_Bool,uint16_t
Function,+,furi_hal_bt_hid_consumer_key_release,_Bool,uint16_t
Function,+,furi_hal_bt_hid_consumer_key_release_all,_Bool,
Function,+,furi_hal_bt_hid_get_led_state,uint8_t,
Function,+,furi_hal_bt_hid_kb_press,_Bool,uint16_t
Function,+,furi_hal_bt_hid_kb_release,_Bool,uint16_t
Function,+,furi_hal_bt_hid_kb_release_all,_Bool,
@@ -1059,6 +1074,7 @@ Function,-,furi_hal_bt_init,void,
Function,+,furi_hal_bt_is_active,_Bool,
Function,+,furi_hal_bt_is_alive,_Bool,
Function,+,furi_hal_bt_is_ble_gatt_gap_supported,_Bool,
Function,+,furi_hal_bt_is_connected,_Bool,
Function,+,furi_hal_bt_is_testing_supported,_Bool,
Function,+,furi_hal_bt_lock_core2,void,
Function,+,furi_hal_bt_nvm_sram_sem_acquire,void,
@@ -1071,6 +1087,9 @@ 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_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,
Function,+,furi_hal_bt_start_app,_Bool,"FuriHalBtProfile, GapEventCallback, void*"
Function,+,furi_hal_bt_start_packet_rx,void,"uint8_t, uint8_t"
@@ -1633,6 +1652,7 @@ Function,-,gamma,double,double
Function,-,gamma_r,double,"double, int*"
Function,-,gammaf,float,float
Function,-,gammaf_r,float,"float, int*"
Function,+,gap_get_remote_conn_rssi,uint32_t,int8_t*
Function,-,gap_get_state,GapState,
Function,-,gap_init,_Bool,"GapConfig*, GapEventCallback, void*"
Function,-,gap_start_advertising,void,
@@ -3334,6 +3354,7 @@ Function,+,subghz_worker_set_pair_callback,void,"SubGhzWorker*, SubGhzWorkerPair
Function,+,subghz_worker_start,void,SubGhzWorker*
Function,+,subghz_worker_stop,void,SubGhzWorker*
Function,+,submenu_add_item,void,"Submenu*, const char*, uint32_t, SubmenuItemCallback, void*"
Function,+,submenu_add_lockable_item,void,"Submenu*, const char*, uint32_t, SubmenuItemCallback, void*, _Bool, const char*"
Function,+,submenu_alloc,Submenu*,
Function,+,submenu_free,void,Submenu*
Function,+,submenu_get_view,View*,Submenu*
@@ -4557,6 +4578,7 @@ Function,+,variable_item_list_set_enter_callback,void,"VariableItemList*, Variab
Function,+,variable_item_list_set_selected_item,void,"VariableItemList*, uint8_t"
Function,+,variable_item_set_current_value_index,void,"VariableItem*, uint8_t"
Function,+,variable_item_set_current_value_text,void,"VariableItem*, const char*"
Function,+,variable_item_set_locked,void,"VariableItem*, _Bool, const char*"
Function,+,variable_item_set_values_count,void,"VariableItem*, uint8_t"
Function,-,vasiprintf,int,"char**, const char*, __gnuc_va_list"
Function,-,vasniprintf,char*,"char*, size_t*, const char*, __gnuc_va_list"
1 entry status name type params
586 Function + ble_glue_thread_stop void
587 Function + ble_glue_wait_for_c2_start _Bool int32_t
588 Function - bsearch void* const void*, const void*, size_t, size_t, __compar_fn_t
589 Function + bt_disable_peer_key_update void Bt*
590 Function + bt_disconnect void Bt*
591 Function + bt_enable_peer_key_update void Bt*
592 Function + bt_forget_bonded_devices void Bt*
593 Function + bt_get_profile_adv_name const char* Bt*
594 Function + bt_get_profile_mac_address const uint8_t* Bt*
595 Function + bt_get_profile_pairing_method GapPairing Bt*
596 Function + bt_keys_storage_set_default_path void Bt*
597 Function + bt_keys_storage_set_storage_path void Bt*, const char*
598 Function + bt_remote_rssi _Bool Bt*, uint8_t*
599 Function + bt_set_profile _Bool Bt*, BtProfile
600 Function + bt_set_profile_adv_name void Bt*, const char*, ...
601 Function + bt_set_profile_mac_address void Bt*, const uint8_t[6]
602 Function + bt_set_profile_pairing_method void Bt*, GapPairing
603 Function + bt_set_status_changed_callback void Bt*, BtStatusChangedCallback, void*
604 Function + buffered_file_stream_alloc Stream* Storage*
605 Function + buffered_file_stream_close _Bool Stream*
825 Function + elements_progress_bar void Canvas*, uint8_t, uint8_t, uint8_t, float
826 Function + elements_progress_bar_with_text void Canvas*, uint8_t, uint8_t, uint8_t, float, const char*
827 Function + elements_scrollable_text_line void Canvas*, uint8_t, uint8_t, uint8_t, FuriString*, size_t, _Bool
828 Function + elements_scrollable_text_line_str void Canvas*, uint8_t, uint8_t, uint8_t, const char*, size_t, _Bool, _Bool
829 Function + elements_scrollbar void Canvas*, uint16_t, uint16_t
830 Function + elements_scrollbar_pos void Canvas*, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t
831 Function + elements_slightly_rounded_box void Canvas*, uint8_t, uint8_t, uint8_t, uint8_t
1047 Function + furi_hal_bt_clear_white_list _Bool
1048 Function + furi_hal_bt_dump_state void FuriString*
1049 Function + furi_hal_bt_ensure_c2_mode _Bool BleGlueC2Mode
1050 Function + furi_hal_bt_get_conn_rssi uint32_t uint8_t*
1051 Function - furi_hal_bt_get_hardfault_info const FuriHalBtHardfaultInfo*
1052 Function + furi_hal_bt_get_key_storage_buff void uint8_t**, uint16_t*
1053 Function + furi_hal_bt_get_profile_adv_name const char* FuriHalBtProfile
1054 Function + furi_hal_bt_get_profile_mac_addr const uint8_t* FuriHalBtProfile
1055 Function + furi_hal_bt_get_profile_pairing_method GapPairing FuriHalBtProfile
1056 Function + furi_hal_bt_get_radio_stack FuriHalBtStack
1057 Function + furi_hal_bt_get_rssi float
1058 Function + furi_hal_bt_get_transmitted_packets uint32_t
1059 Function + furi_hal_bt_hid_consumer_key_press _Bool uint16_t
1060 Function + furi_hal_bt_hid_consumer_key_release _Bool uint16_t
1061 Function + furi_hal_bt_hid_consumer_key_release_all _Bool
1062 Function + furi_hal_bt_hid_get_led_state uint8_t
1063 Function + furi_hal_bt_hid_kb_press _Bool uint16_t
1064 Function + furi_hal_bt_hid_kb_release _Bool uint16_t
1065 Function + furi_hal_bt_hid_kb_release_all _Bool
1074 Function + furi_hal_bt_is_active _Bool
1075 Function + furi_hal_bt_is_alive _Bool
1076 Function + furi_hal_bt_is_ble_gatt_gap_supported _Bool
1077 Function + furi_hal_bt_is_connected _Bool
1078 Function + furi_hal_bt_is_testing_supported _Bool
1079 Function + furi_hal_bt_lock_core2 void
1080 Function + furi_hal_bt_nvm_sram_sem_acquire void
1087 Function + furi_hal_bt_serial_stop void
1088 Function + furi_hal_bt_serial_tx _Bool uint8_t*, uint16_t
1089 Function + furi_hal_bt_set_key_storage_change_callback void BleGlueKeyStorageChangedCallback, void*
1090 Function + furi_hal_bt_set_profile_adv_name void FuriHalBtProfile, const char[( 18 + 1 )]
1091 Function + furi_hal_bt_set_profile_mac_addr void FuriHalBtProfile, const uint8_t[( 6 )]
1092 Function + furi_hal_bt_set_profile_pairing_method void FuriHalBtProfile, GapPairing
1093 Function + furi_hal_bt_start_advertising void
1094 Function + furi_hal_bt_start_app _Bool FuriHalBtProfile, GapEventCallback, void*
1095 Function + furi_hal_bt_start_packet_rx void uint8_t, uint8_t
1652 Function - gamma_r double double, int*
1653 Function - gammaf float float
1654 Function - gammaf_r float float, int*
1655 Function + gap_get_remote_conn_rssi uint32_t int8_t*
1656 Function - gap_get_state GapState
1657 Function - gap_init _Bool GapConfig*, GapEventCallback, void*
1658 Function - gap_start_advertising void
3354 Function + subghz_worker_start void SubGhzWorker*
3355 Function + subghz_worker_stop void SubGhzWorker*
3356 Function + submenu_add_item void Submenu*, const char*, uint32_t, SubmenuItemCallback, void*
3357 Function + submenu_add_lockable_item void Submenu*, const char*, uint32_t, SubmenuItemCallback, void*, _Bool, const char*
3358 Function + submenu_alloc Submenu*
3359 Function + submenu_free void Submenu*
3360 Function + submenu_get_view View* Submenu*
4578 Function + variable_item_list_set_selected_item void VariableItemList*, uint8_t
4579 Function + variable_item_set_current_value_index void VariableItem*, uint8_t
4580 Function + variable_item_set_current_value_text void VariableItem*, const char*
4581 Function + variable_item_set_locked void VariableItem*, _Bool, const char*
4582 Function + variable_item_set_values_count void VariableItem*, uint8_t
4583 Function - vasiprintf int char**, const char*, __gnuc_va_list
4584 Function - vasniprintf char* char*, size_t*, const char*, __gnuc_va_list
+55 -4
View File
@@ -28,6 +28,8 @@ typedef struct {
GapConfig* config;
GapConnectionParams connection_params;
GapState state;
int8_t conn_rssi;
uint32_t time_rssi_sample;
FuriMutex* state_mutex;
GapEventCallback on_event_cb;
void* context;
@@ -56,6 +58,19 @@ static Gap* gap = NULL;
static void gap_advertise_start(GapState new_state);
static int32_t gap_app(void* context);
/** function for updating rssi informations in global Gap object
*
*/
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_D(TAG, "Failed to read RSSI");
}
static void gap_verify_connection_parameters(Gap* gap) {
furi_assert(gap);
@@ -128,6 +143,9 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
gap->connection_params.supervisor_timeout = event->Supervision_Timeout;
FURI_LOG_I(TAG, "Connection parameters event complete");
gap_verify_connection_parameters(gap);
// Save rssi for current connection
fetch_rssi();
break;
}
@@ -162,6 +180,9 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
gap->service.connection_handle = event->Connection_Handle;
gap_verify_connection_parameters(gap);
// Save rssi for current connection
fetch_rssi();
// Start pairing by sending security request
aci_gap_slave_security_req(event->Connection_Handle);
} break;
@@ -242,6 +263,9 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
pairing_complete->Status);
aci_gap_terminate(gap->service.connection_handle, 5);
} else {
// Save RSSI
fetch_rssi();
FURI_LOG_I(TAG, "Pairing complete");
GapEvent event = {.type = GapEventTypeConnected};
gap->on_event_cb(event, gap->context); //-V595
@@ -310,7 +334,7 @@ static void gap_init_svc(Gap* gap) {
// Initialize GATT interface
aci_gatt_init();
// Initialize GAP interface
// Skip fist symbol AD_TYPE_COMPLETE_LOCAL_NAME
// Skip first symbol AD_TYPE_COMPLETE_LOCAL_NAME
char* name = gap->service.adv_name + 1;
aci_gap_init(
GAP_PERIPHERAL_ROLE,
@@ -345,21 +369,34 @@ static void gap_init_svc(Gap* gap) {
hci_le_set_default_phy(ALL_PHYS_PREFERENCE, TX_2M_PREFERRED, RX_2M_PREFERRED);
// Set I/O capability
bool keypress_supported = false;
// New things below
uint8_t conf_mitm = CFG_MITM_PROTECTION;
uint8_t conf_used_fixed_pin = CFG_USED_FIXED_PIN;
bool conf_bonding = gap->config->bonding_mode;
if(gap->config->pairing_method == GapPairingPinCodeShow) {
aci_gap_set_io_capability(IO_CAP_DISPLAY_ONLY);
} else if(gap->config->pairing_method == GapPairingPinCodeVerifyYesNo) {
aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO);
keypress_supported = true;
} else if(gap->config->pairing_method == GapPairingNone) {
// Just works pairing method (IOS accept it, it seems android and linux doesn't)
conf_mitm = 0;
conf_used_fixed_pin = 0;
conf_bonding = false;
// if just works isn't supported, we want the numeric comparaison method
aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO);
keypress_supported = true;
}
// Setup authentication
aci_gap_set_authentication_requirement(
gap->config->bonding_mode,
CFG_MITM_PROTECTION,
conf_bonding,
conf_mitm,
CFG_SC_SUPPORT,
keypress_supported,
CFG_ENCRYPTION_KEY_SIZE_MIN,
CFG_ENCRYPTION_KEY_SIZE_MAX,
CFG_USED_FIXED_PIN,
conf_used_fixed_pin, // 0x0 for no pin
0,
CFG_IDENTITY_ADDRESS);
// Configure whitelist
@@ -488,6 +525,9 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
gap->service.connection_handle = 0xFFFF;
gap->enable_adv = true;
gap->conn_rssi = 127;
gap->time_rssi_sample = 0;
// Thread configuration
gap->thread = furi_thread_alloc_ex("BleGapDriver", 1024, gap_app, gap);
furi_thread_start(gap->thread);
@@ -507,6 +547,17 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
return true;
}
// Get RSSI
uint32_t gap_get_remote_conn_rssi(int8_t* rssi) {
if(gap && gap->state == GapStateConnected) {
fetch_rssi();
*rssi = gap->conn_rssi;
if(gap->time_rssi_sample) return furi_get_tick() - gap->time_rssi_sample;
}
return 0;
}
GapState gap_get_state() {
GapState state;
if(gap) {
+2
View File
@@ -81,6 +81,8 @@ GapState gap_get_state();
void gap_thread_stop();
uint32_t gap_get_remote_conn_rssi(int8_t* rssi);
#ifdef __cplusplus
}
#endif
+86 -2
View File
@@ -14,6 +14,11 @@ typedef struct {
uint16_t report_map_char_handle;
uint16_t info_char_handle;
uint16_t ctrl_point_char_handle;
// led state
uint16_t led_state_char_handle;
uint16_t led_state_desc_handle;
HidLedStateEventCallback led_state_event_callback;
void* led_state_ctx;
} HIDSvc;
static HIDSvc* hid_svc = NULL;
@@ -30,6 +35,32 @@ static SVCCTL_EvtAckStatus_t hid_svc_event_handler(void* event) {
} else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
// Process notification confirmation
ret = SVCCTL_EvtAckFlowEnable;
} else if(blecore_evt->ecode == ACI_GATT_WRITE_PERMIT_REQ_VSEVT_CODE) {
// Process write request
aci_gatt_write_permit_req_event_rp0* req =
(aci_gatt_write_permit_req_event_rp0*)blecore_evt->data;
furi_check(hid_svc->led_state_event_callback && hid_svc->led_state_ctx);
// this check is likely to be incorrect, it will actually work in our case
// but we need to investigate gatt api to see what is the rules
// that specify attibute handle value from char handle (or the reverse)
if(req->Attribute_Handle == (hid_svc->led_state_char_handle + 1)) {
hid_svc->led_state_event_callback(req->Data[0], hid_svc->led_state_ctx);
aci_gatt_write_resp(
req->Connection_Handle,
req->Attribute_Handle,
0x00, /* write_status = 0 (no error))*/
0x00, /* err_code */
req->Data_Length,
req->Data);
aci_gatt_write_char_value(
req->Connection_Handle,
hid_svc->led_state_char_handle,
req->Data_Length,
req->Data);
ret = SVCCTL_EvtAckFlowEnable;
}
}
}
return ret;
@@ -55,8 +86,8 @@ void hid_svc_start() {
PRIMARY_SERVICE,
2 + /* protocol mode */
(4 * HID_SVC_INPUT_REPORT_COUNT) + (3 * HID_SVC_OUTPUT_REPORT_COUNT) +
(3 * HID_SVC_FEATURE_REPORT_COUNT) + 1 + 2 + 2 +
2, /* Service + Report Map + HID Information + HID Control Point */
(3 * HID_SVC_FEATURE_REPORT_COUNT) + 1 + 2 + 2 + 2 +
4, /* Service + Report Map + HID Information + HID Control Point + LED state */
&hid_svc->svc_handle);
if(status) {
FURI_LOG_E(TAG, "Failed to add HID service: %d", status);
@@ -198,6 +229,43 @@ void hid_svc_start() {
}
}
#endif
// Add led state output report
char_uuid.Char_UUID_16 = REPORT_CHAR_UUID;
status = aci_gatt_add_char(
hid_svc->svc_handle,
UUID_TYPE_16,
&char_uuid,
1,
CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE,
ATTR_PERMISSION_NONE,
GATT_NOTIFY_ATTRIBUTE_WRITE | GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP,
10,
CHAR_VALUE_LEN_CONSTANT,
&(hid_svc->led_state_char_handle));
if(status) {
FURI_LOG_E(TAG, "Failed to add led state characteristic: %d", status);
}
// Add led state char descriptor specifying it is an output report
uint8_t buf[2] = {HID_SVC_REPORT_COUNT + 1, 2};
desc_uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID;
status = aci_gatt_add_char_desc(
hid_svc->svc_handle,
hid_svc->led_state_char_handle,
UUID_TYPE_16,
&desc_uuid,
HID_SVC_REPORT_REF_LEN,
HID_SVC_REPORT_REF_LEN,
buf,
ATTR_PERMISSION_NONE,
ATTR_ACCESS_READ_WRITE,
GATT_DONT_NOTIFY_EVENTS,
MIN_ENCRY_KEY_SIZE,
CHAR_VALUE_LEN_CONSTANT,
&(hid_svc->led_state_desc_handle));
if(status) {
FURI_LOG_E(TAG, "Failed to add led state descriptor: %d", status);
}
// Add Report Map characteristic
char_uuid.Char_UUID_16 = REPORT_MAP_CHAR_UUID;
status = aci_gatt_add_char(
@@ -247,6 +315,9 @@ void hid_svc_start() {
if(status) {
FURI_LOG_E(TAG, "Failed to add control point characteristic: %d", status);
}
hid_svc->led_state_event_callback = NULL;
hid_svc->led_state_ctx = NULL;
}
bool hid_svc_update_report_map(const uint8_t* data, uint16_t len) {
@@ -288,6 +359,15 @@ bool hid_svc_update_info(uint8_t* data, uint16_t len) {
return true;
}
void hid_svc_register_led_state_callback(HidLedStateEventCallback callback, void* context) {
furi_assert(hid_svc);
furi_assert(callback);
furi_assert(context);
hid_svc->led_state_event_callback = callback;
hid_svc->led_state_ctx = context;
}
bool hid_svc_is_started() {
return hid_svc != NULL;
}
@@ -320,6 +400,10 @@ void hid_svc_stop() {
if(status) {
FURI_LOG_E(TAG, "Failed to delete Control Point characteristic: %d", status);
}
status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->led_state_char_handle);
if(status) {
FURI_LOG_E(TAG, "Failed to delete led state characteristic: %d", status);
}
// Delete service
status = aci_gatt_del_service(hid_svc->svc_handle);
if(status) {
@@ -15,6 +15,8 @@
#define HID_SVC_REPORT_COUNT \
(HID_SVC_INPUT_REPORT_COUNT + HID_SVC_OUTPUT_REPORT_COUNT + HID_SVC_FEATURE_REPORT_COUNT)
typedef uint16_t (*HidLedStateEventCallback)(uint8_t state, void* ctx);
void hid_svc_start();
void hid_svc_stop();
@@ -26,3 +28,5 @@ bool hid_svc_update_report_map(const uint8_t* data, uint16_t len);
bool hid_svc_update_input_report(uint8_t input_report_num, uint8_t* data, uint16_t len);
bool hid_svc_update_info(uint8_t* data, uint16_t len);
void hid_svc_register_led_state_callback(HidLedStateEventCallback callback, void* context);
+92 -14
View File
@@ -199,26 +199,39 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb,
FURI_LOG_E(TAG, "Can't start Ble App - unsupported radio stack");
break;
}
// Set mac address
memcpy(
profile_config[profile].config.mac_address,
furi_hal_version_get_ble_mac(),
sizeof(profile_config[profile].config.mac_address));
// Set advertise name
strlcpy(
profile_config[profile].config.adv_name,
furi_hal_version_get_ble_local_device_name_ptr(),
FURI_HAL_VERSION_DEVICE_NAME_LENGTH);
// Configure GAP
GapConfig* config = &profile_config[profile].config;
// Configure GAP
if(profile == FuriHalBtProfileSerial) {
// Set mac address
memcpy(
config->mac_address, furi_hal_version_get_ble_mac(), sizeof(config->mac_address));
// Set advertise name
strlcpy(
config->adv_name,
furi_hal_version_get_ble_local_device_name_ptr(),
FURI_HAL_VERSION_DEVICE_NAME_LENGTH);
config->adv_service_uuid |= furi_hal_version_get_hw_color();
} else if(profile == FuriHalBtProfileHidKeyboard) {
// Change MAC address for HID profile
config->mac_address[2]++;
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) {
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
const char* clicker_str = "Control";
memcpy(&config->adv_name[1], clicker_str, strlen(clicker_str));
if(strnlen(config->adv_name, FURI_HAL_VERSION_DEVICE_NAME_LENGTH) < 2 ||
strnlen(config->adv_name + 1, FURI_HAL_VERSION_DEVICE_NAME_LENGTH) < 1) {
snprintf(
config->adv_name,
FURI_HAL_VERSION_DEVICE_NAME_LENGTH,
"%cControl %s",
*furi_hal_version_get_ble_local_device_name_ptr(),
furi_hal_version_get_ble_local_device_name_ptr() + 9);
}
}
if(!gap_init(config, event_cb, context)) {
gap_thread_stop();
@@ -280,6 +293,10 @@ bool furi_hal_bt_is_active() {
return gap_get_state() > GapStateIdle;
}
bool furi_hal_bt_is_connected() {
return gap_get_state() == GapStateConnected;
}
void furi_hal_bt_start_advertising() {
if(gap_get_state() == GapStateIdle) {
gap_start_advertising();
@@ -418,6 +435,67 @@ float furi_hal_bt_get_rssi() {
return val;
}
/** fill the RSSI of the remote host of the bt connection and returns the last
* time the RSSI was updated
*
*/
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;
}
void furi_hal_bt_set_profile_adv_name(
FuriHalBtProfile profile,
const char name[FURI_HAL_BT_ADV_NAME_LENGTH]) {
furi_assert(profile < FuriHalBtProfileNumber);
furi_assert(name);
if(strlen(name) == 0) {
memset(
&(profile_config[profile].config.adv_name[1]),
0,
strlen(&(profile_config[profile].config.adv_name[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);
}
}
const char* furi_hal_bt_get_profile_adv_name(FuriHalBtProfile profile) {
furi_assert(profile < FuriHalBtProfileNumber);
return &(profile_config[profile].config.adv_name[1]);
}
void furi_hal_bt_set_profile_mac_addr(
FuriHalBtProfile profile,
const uint8_t mac_addr[GAP_MAC_ADDR_SIZE]) {
furi_assert(profile < FuriHalBtProfileNumber);
furi_assert(mac_addr);
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) {
furi_assert(profile < FuriHalBtProfileNumber);
return profile_config[profile].config.mac_address;
}
void furi_hal_bt_set_profile_pairing_method(FuriHalBtProfile profile, GapPairing pairing_method) {
furi_assert(profile < FuriHalBtProfileNumber);
profile_config[profile].config.pairing_method = pairing_method;
}
GapPairing furi_hal_bt_get_profile_pairing_method(FuriHalBtProfile profile) {
furi_assert(profile < FuriHalBtProfileNumber);
return profile_config[profile].config.pairing_method;
}
uint32_t furi_hal_bt_get_transmitted_packets() {
uint32_t packets = 0;
aci_hal_le_tx_test_packet_number(&packets);
+74 -1
View File
@@ -20,6 +20,7 @@ enum HidReportId {
ReportIdKeyboard = 1,
ReportIdMouse = 2,
ReportIdConsumer = 3,
ReportIdLEDState = 4,
};
// Report numbers corresponded to the report id with an offset of 1
enum HidInputNumber {
@@ -77,6 +78,13 @@ static const uint8_t furi_hal_bt_hid_report_map_data[] = {
HID_USAGE_MINIMUM(0),
HID_USAGE_MAXIMUM(101),
HID_INPUT(HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
HID_REPORT_ID(ReportIdLEDState),
HID_USAGE_PAGE(HID_PAGE_LED),
HID_REPORT_COUNT(8),
HID_REPORT_SIZE(1),
HID_USAGE_MINIMUM(1),
HID_USAGE_MAXIMUM(8),
HID_OUTPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_END_COLLECTION,
// Mouse Report
HID_USAGE_PAGE(HID_PAGE_DESKTOP),
@@ -125,6 +133,63 @@ FuriHalBtHidKbReport* kb_report = NULL;
FuriHalBtHidMouseReport* mouse_report = NULL;
FuriHalBtHidConsumerReport* consumer_report = NULL;
typedef struct {
// shortcuts
#define s_undefined data.bits.b_undefined
#define s_num_lock data.bits.b_num_lock
#define s_caps_lock data.bits.b_caps_lock
#define s_scroll_lock data.bits.b_scroll_lock
#define s_compose data.bits.b_compose
#define s_kana data.bits.b_kana
#define s_power data.bits.b_power
#define s_shift data.bits.b_shift
#define s_value data.value
union {
struct {
uint8_t b_undefined : 1;
uint8_t b_num_lock : 1;
uint8_t b_caps_lock : 1;
uint8_t b_scroll_lock : 1;
uint8_t b_compose : 1;
uint8_t b_kana : 1;
uint8_t b_power : 1;
uint8_t b_shift : 1;
} bits;
uint8_t value;
} data;
} __attribute__((__packed__)) FuriHalBtHidLedState;
FuriHalBtHidLedState hid_host_led_state = {.s_value = 0};
uint16_t furi_hal_bt_hid_led_state_cb(uint8_t state, void* ctx) {
FuriHalBtHidLedState* led_state = (FuriHalBtHidLedState*)ctx;
//FURI_LOG_D("HalBtHid", "LED state updated !");
led_state->s_value = state;
return 0;
}
uint8_t furi_hal_bt_hid_get_led_state(void) {
/*FURI_LOG_D(
"HalBtHid",
"LED state: RFU=%d NUMLOCK=%d CAPSLOCK=%d SCROLLLOCK=%d COMPOSE=%d KANA=%d POWER=%d SHIFT=%d",
hid_host_led_state.s_undefined,
hid_host_led_state.s_num_lock,
hid_host_led_state.s_caps_lock,
hid_host_led_state.s_scroll_lock,
hid_host_led_state.s_compose,
hid_host_led_state.s_kana,
hid_host_led_state.s_power,
hid_host_led_state.s_shift);
*/
return (hid_host_led_state.s_value >> 1); // bit 0 is undefined (after shift bit location
// match with HID led state bits defines)
// see bad_bt_script.c (ducky_numlock_on function)
}
void furi_hal_bt_hid_start() {
// Start device info
if(!dev_info_svc_is_started()) {
@@ -139,6 +204,8 @@ void furi_hal_bt_hid_start() {
hid_svc_start();
}
// Configure HID Keyboard
hid_svc_register_led_state_callback(furi_hal_bt_hid_led_state_cb, &hid_host_led_state);
kb_report = malloc(sizeof(FuriHalBtHidKbReport));
mouse_report = malloc(sizeof(FuriHalBtHidMouseReport));
consumer_report = malloc(sizeof(FuriHalBtHidConsumerReport));
@@ -160,6 +227,8 @@ void furi_hal_bt_hid_stop() {
furi_assert(kb_report);
furi_assert(mouse_report);
furi_assert(consumer_report);
hid_svc_register_led_state_callback(NULL, NULL);
// Stop all services
if(dev_info_svc_is_started()) {
dev_info_svc_stop();
@@ -180,12 +249,16 @@ void furi_hal_bt_hid_stop() {
bool furi_hal_bt_hid_kb_press(uint16_t button) {
furi_assert(kb_report);
for(uint8_t i = 0; i < FURI_HAL_BT_HID_KB_MAX_KEYS; i++) {
uint8_t i;
for(i = 0; i < FURI_HAL_BT_HID_KB_MAX_KEYS; i++) {
if(kb_report->key[i] == 0) {
kb_report->key[i] = button & 0xFF;
break;
}
}
if(i == FURI_HAL_BT_HID_KB_MAX_KEYS) {
return false;
}
kb_report->mods |= (button >> 8);
return hid_svc_update_input_report(
ReportNumberKeyboard, (uint8_t*)kb_report, sizeof(FuriHalBtHidKbReport));
@@ -218,6 +218,35 @@ float furi_hal_bt_get_rssi();
*/
uint32_t furi_hal_bt_get_transmitted_packets();
// BadBT stuff
/** 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_BT_ADV_NAME_LENGTH]);
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]);
const uint8_t* furi_hal_bt_get_profile_mac_addr(FuriHalBtProfile profile);
uint32_t furi_hal_bt_get_conn_rssi(uint8_t* rssi);
void furi_hal_bt_set_profile_pairing_method(FuriHalBtProfile profile, GapPairing pairing_method);
GapPairing furi_hal_bt_get_profile_pairing_method(FuriHalBtProfile profile);
bool furi_hal_bt_is_connected(void);
/** Check & switch C2 to given mode
*
* @param[in] mode mode to switch into
@@ -86,6 +86,13 @@ bool furi_hal_bt_hid_consumer_key_release(uint16_t button);
*/
bool furi_hal_bt_hid_consumer_key_release_all();
/** Retrieves LED state from remote BT HID host
*
* @return (look at HID usage page to know what each bit of the returned byte means)
* NB: RFU bit has been shifted out in the returned octet so USB defines should work
*/
uint8_t furi_hal_bt_hid_get_led_state(void);
#ifdef __cplusplus
}
#endif
@@ -16,6 +16,7 @@ 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)