mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-14 04:58:36 -07:00
New more streamlined custom ble adv api
Thanks for the idea @xMasterX !
This commit is contained in:
@@ -355,25 +355,45 @@ static int32_t adv_thread(void* ctx) {
|
|||||||
Payload* payload = state->payload;
|
Payload* payload = state->payload;
|
||||||
ContinuityMsg* msg = &payload->msg;
|
ContinuityMsg* msg = &payload->msg;
|
||||||
ContinuityType type = msg->type;
|
ContinuityType type = msg->type;
|
||||||
|
|
||||||
while(state->advertising) {
|
while(state->advertising) {
|
||||||
if(payload->random) {
|
if(payload->random) {
|
||||||
size_t random_i = rand() % randoms[type].count;
|
size_t random_i = rand() % randoms[type].count;
|
||||||
memcpy(&msg->data, randoms[type].datas[random_i], sizeof(msg->data));
|
memcpy(&msg->data, randoms[type].datas[random_i], sizeof(msg->data));
|
||||||
}
|
}
|
||||||
continuity_generate_packet(msg, state->packet);
|
continuity_generate_packet(msg, state->packet);
|
||||||
furi_hal_bt_set_custom_adv_data(state->packet, state->size);
|
furi_hal_bt_custom_adv_set(state->packet, state->size);
|
||||||
furi_thread_flags_wait(true, FuriFlagWaitAny, state->delay);
|
furi_thread_flags_wait(true, FuriFlagWaitAny, state->delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stop_adv(State* state) {
|
||||||
|
state->advertising = false;
|
||||||
|
furi_thread_flags_set(furi_thread_get_id(state->thread), true);
|
||||||
|
furi_thread_join(state->thread);
|
||||||
|
furi_hal_bt_custom_adv_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void start_adv(State* state) {
|
||||||
|
state->advertising = true;
|
||||||
|
furi_thread_start(state->thread);
|
||||||
|
uint8_t mac[GAP_MAC_ADDR_SIZE] = {
|
||||||
|
rand() % 256,
|
||||||
|
rand() % 256,
|
||||||
|
rand() % 256,
|
||||||
|
rand() % 256,
|
||||||
|
rand() % 256,
|
||||||
|
rand() % 256,
|
||||||
|
};
|
||||||
|
furi_hal_bt_custom_adv_start(state->delay, state->delay, 0x00, mac, 0x1F);
|
||||||
|
}
|
||||||
|
|
||||||
static void toggle_adv(State* state, Payload* payload) {
|
static void toggle_adv(State* state, Payload* payload) {
|
||||||
if(state->advertising) {
|
if(state->advertising) {
|
||||||
state->advertising = false;
|
stop_adv(state);
|
||||||
furi_thread_flags_set(furi_thread_get_id(state->thread), true);
|
|
||||||
furi_thread_join(state->thread);
|
|
||||||
state->payload = NULL;
|
state->payload = NULL;
|
||||||
furi_hal_bt_set_custom_adv_data(NULL, 0);
|
|
||||||
free(state->packet);
|
free(state->packet);
|
||||||
state->packet = NULL;
|
state->packet = NULL;
|
||||||
state->size = 0;
|
state->size = 0;
|
||||||
@@ -381,8 +401,7 @@ static void toggle_adv(State* state, Payload* payload) {
|
|||||||
state->size = continuity_get_packet_size(payload->msg.type);
|
state->size = continuity_get_packet_size(payload->msg.type);
|
||||||
state->packet = malloc(state->size);
|
state->packet = malloc(state->size);
|
||||||
state->payload = payload;
|
state->payload = payload;
|
||||||
state->advertising = true;
|
start_adv(state);
|
||||||
furi_thread_start(state->thread);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,36 +483,39 @@ int32_t apple_ble_spam(void* p) {
|
|||||||
furi_check(furi_message_queue_get(input_queue, &input, FuriWaitForever) == FuriStatusOk);
|
furi_check(furi_message_queue_get(input_queue, &input, FuriWaitForever) == FuriStatusOk);
|
||||||
|
|
||||||
Payload* payload = &payloads[state->index];
|
Payload* payload = &payloads[state->index];
|
||||||
|
bool advertising = state->advertising;
|
||||||
switch(input.key) {
|
switch(input.key) {
|
||||||
case InputKeyOk:
|
case InputKeyOk:
|
||||||
toggle_adv(state, payload);
|
toggle_adv(state, payload);
|
||||||
break;
|
break;
|
||||||
case InputKeyUp:
|
case InputKeyUp:
|
||||||
if(state->delay < 5000) {
|
if(state->delay < 5000) {
|
||||||
|
if(advertising) stop_adv(state);
|
||||||
state->delay += 100;
|
state->delay += 100;
|
||||||
furi_thread_flags_set(furi_thread_get_id(state->thread), true);
|
if(advertising) start_adv(state);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InputKeyDown:
|
case InputKeyDown:
|
||||||
if(state->delay > 100) {
|
if(state->delay > 100) {
|
||||||
|
if(advertising) stop_adv(state);
|
||||||
state->delay -= 100;
|
state->delay -= 100;
|
||||||
furi_thread_flags_set(furi_thread_get_id(state->thread), true);
|
if(advertising) start_adv(state);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InputKeyLeft:
|
case InputKeyLeft:
|
||||||
if(state->index > 0) {
|
if(state->index > 0) {
|
||||||
if(state->advertising) toggle_adv(state, payload);
|
if(advertising) toggle_adv(state, payload);
|
||||||
state->index--;
|
state->index--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InputKeyRight:
|
case InputKeyRight:
|
||||||
if(state->index < COUNT_OF(payloads) - 1) {
|
if(state->index < COUNT_OF(payloads) - 1) {
|
||||||
if(state->advertising) toggle_adv(state, payload);
|
if(advertising) toggle_adv(state, payload);
|
||||||
state->index++;
|
state->index++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InputKeyBack:
|
case InputKeyBack:
|
||||||
if(state->advertising) toggle_adv(state, payload);
|
if(advertising) toggle_adv(state, payload);
|
||||||
running = false;
|
running = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1075,6 +1075,9 @@ Function,+,furi_event_flag_wait,uint32_t,"FuriEventFlag*, uint32_t, uint32_t, ui
|
|||||||
Function,+,furi_get_tick,uint32_t,
|
Function,+,furi_get_tick,uint32_t,
|
||||||
Function,+,furi_hal_bt_change_app,_Bool,"FuriHalBtProfile, GapEventCallback, void*"
|
Function,+,furi_hal_bt_change_app,_Bool,"FuriHalBtProfile, GapEventCallback, void*"
|
||||||
Function,+,furi_hal_bt_clear_white_list,_Bool,
|
Function,+,furi_hal_bt_clear_white_list,_Bool,
|
||||||
|
Function,+,furi_hal_bt_custom_adv_set,_Bool,"const uint8_t*, size_t"
|
||||||
|
Function,+,furi_hal_bt_custom_adv_start,_Bool,"uint16_t, uint16_t, uint8_t, const uint8_t[( 6 )], uint8_t"
|
||||||
|
Function,+,furi_hal_bt_custom_adv_stop,_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_conn_rssi,uint32_t,uint8_t*
|
||||||
@@ -1117,7 +1120,6 @@ Function,+,furi_hal_bt_serial_set_rpc_status,void,FuriHalBtSerialRpcStatus
|
|||||||
Function,+,furi_hal_bt_serial_start,void,
|
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_custom_adv_data,void,"const uint8_t*, size_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[( 18 + 1 )]"
|
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_mac_addr,void,"FuriHalBtProfile, const uint8_t[( 6 )]"
|
||||||
@@ -1705,7 +1707,6 @@ Function,-,gammaf_r,float,"float, int*"
|
|||||||
Function,-,gap_get_remote_conn_rssi,uint32_t,int8_t*
|
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_set_custom_adv_data,void,"size_t, const uint8_t*"
|
|
||||||
Function,-,gap_start_advertising,void,
|
Function,-,gap_start_advertising,void,
|
||||||
Function,-,gap_stop_advertising,void,
|
Function,-,gap_stop_advertising,void,
|
||||||
Function,-,gap_thread_stop,void,
|
Function,-,gap_thread_stop,void,
|
||||||
|
|||||||
|
@@ -37,9 +37,6 @@ typedef struct {
|
|||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
FuriMessageQueue* command_queue;
|
FuriMessageQueue* command_queue;
|
||||||
bool enable_adv;
|
bool enable_adv;
|
||||||
|
|
||||||
size_t custom_adv_len;
|
|
||||||
const uint8_t* custom_adv_data;
|
|
||||||
} Gap;
|
} Gap;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -434,34 +431,18 @@ static void gap_advertise_start(GapState new_state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Configure advertising
|
// Configure advertising
|
||||||
if(gap->custom_adv_data) {
|
status = aci_gap_set_discoverable(
|
||||||
// Custom adv logic from https://techryptic.github.io/2023/09/01/Annoying-Apple-Fans/
|
ADV_IND,
|
||||||
static const uint16_t gap_appearance = 0x0000; //GAP_APPEARANCE_UNKNOWN
|
min_interval,
|
||||||
status = aci_gatt_update_char_value(
|
max_interval,
|
||||||
gap->service.gap_svc_handle,
|
CFG_IDENTITY_ADDRESS,
|
||||||
gap->service.gap_svc_handle,
|
0,
|
||||||
0,
|
strlen(gap->service.adv_name),
|
||||||
sizeof(gap_appearance),
|
(uint8_t*)gap->service.adv_name,
|
||||||
(uint8_t*)&gap_appearance);
|
gap->service.adv_svc_uuid_len,
|
||||||
status = aci_gap_set_discoverable(
|
gap->service.adv_svc_uuid,
|
||||||
ADV_IND, min_interval, max_interval, CFG_IDENTITY_ADDRESS, 0, 0, NULL, 0, NULL, 0, 0);
|
0,
|
||||||
status = aci_gap_delete_ad_type(AD_TYPE_FLAGS);
|
0);
|
||||||
status = aci_gap_delete_ad_type(AD_TYPE_TX_POWER_LEVEL);
|
|
||||||
status = aci_gap_update_adv_data(gap->custom_adv_len, gap->custom_adv_data);
|
|
||||||
} else {
|
|
||||||
status = aci_gap_set_discoverable(
|
|
||||||
ADV_IND,
|
|
||||||
min_interval,
|
|
||||||
max_interval,
|
|
||||||
CFG_IDENTITY_ADDRESS,
|
|
||||||
0,
|
|
||||||
strlen(gap->service.adv_name),
|
|
||||||
(uint8_t*)gap->service.adv_name,
|
|
||||||
gap->service.adv_svc_uuid_len,
|
|
||||||
gap->service.adv_svc_uuid,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
if(status) {
|
if(status) {
|
||||||
FURI_LOG_E(TAG, "set_discoverable failed %d", status);
|
FURI_LOG_E(TAG, "set_discoverable failed %d", status);
|
||||||
} else {
|
} else {
|
||||||
@@ -581,11 +562,6 @@ uint32_t gap_get_remote_conn_rssi(int8_t* rssi) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gap_set_custom_adv_data(size_t adv_len, const uint8_t* adv_data) {
|
|
||||||
gap->custom_adv_len = adv_len;
|
|
||||||
gap->custom_adv_data = adv_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
GapState gap_get_state() {
|
GapState gap_get_state() {
|
||||||
GapState state;
|
GapState state;
|
||||||
if(gap) {
|
if(gap) {
|
||||||
|
|||||||
@@ -83,8 +83,6 @@ void gap_thread_stop();
|
|||||||
|
|
||||||
uint32_t gap_get_remote_conn_rssi(int8_t* rssi);
|
uint32_t gap_get_remote_conn_rssi(int8_t* rssi);
|
||||||
|
|
||||||
void gap_set_custom_adv_data(size_t adv_len, const uint8_t* adv_data);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -483,10 +483,48 @@ uint32_t furi_hal_bt_get_conn_rssi(uint8_t* rssi) {
|
|||||||
return since;
|
return since;
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_bt_set_custom_adv_data(const uint8_t* adv_data, size_t adv_len) {
|
bool furi_hal_bt_custom_adv_set(const uint8_t* adv_data, size_t adv_len) {
|
||||||
gap_set_custom_adv_data(adv_len, adv_data);
|
tBleStatus status = aci_gap_additional_beacon_set_data(adv_len, adv_data);
|
||||||
furi_hal_bt_stop_advertising();
|
if(status) {
|
||||||
furi_hal_bt_start_advertising();
|
FURI_LOG_E(TAG, "custom_adv_set failed %d", status);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(TAG, "custom_adv_set success");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool furi_hal_bt_custom_adv_start(
|
||||||
|
uint16_t min_interval,
|
||||||
|
uint16_t max_interval,
|
||||||
|
uint8_t mac_type,
|
||||||
|
const uint8_t mac_addr[GAP_MAC_ADDR_SIZE],
|
||||||
|
uint8_t power_amp_level) {
|
||||||
|
tBleStatus status = aci_gap_additional_beacon_start(
|
||||||
|
min_interval / 0.625, // Millis to gap time
|
||||||
|
max_interval / 0.625, // Millis to gap time
|
||||||
|
0b00000111, // All 3 channels
|
||||||
|
mac_type,
|
||||||
|
mac_addr,
|
||||||
|
power_amp_level);
|
||||||
|
if(status) {
|
||||||
|
FURI_LOG_E(TAG, "custom_adv_start failed %d", status);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(TAG, "custom_adv_start success");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool furi_hal_bt_custom_adv_stop() {
|
||||||
|
tBleStatus status = aci_gap_additional_beacon_stop();
|
||||||
|
if(status) {
|
||||||
|
FURI_LOG_E(TAG, "custom_adv_stop failed %d", status);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(TAG, "custom_adv_stop success");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_bt_reverse_mac_addr(uint8_t mac_addr[GAP_MAC_ADDR_SIZE]) {
|
void furi_hal_bt_reverse_mac_addr(uint8_t mac_addr[GAP_MAC_ADDR_SIZE]) {
|
||||||
|
|||||||
@@ -251,7 +251,35 @@ const uint8_t* furi_hal_bt_get_profile_mac_addr(FuriHalBtProfile profile);
|
|||||||
|
|
||||||
uint32_t furi_hal_bt_get_conn_rssi(uint8_t* rssi);
|
uint32_t furi_hal_bt_get_conn_rssi(uint8_t* rssi);
|
||||||
|
|
||||||
void furi_hal_bt_set_custom_adv_data(const uint8_t* adv_data, size_t adv_len);
|
/** Set custom advertisement packet data
|
||||||
|
* @param[in] adv_data pointer to advertisement data
|
||||||
|
* @param[in] adv_len length of advertisement data
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool furi_hal_bt_custom_adv_set(const uint8_t* adv_data, size_t adv_len);
|
||||||
|
|
||||||
|
/** Start custom advertisement beacon
|
||||||
|
* @param[in] min_interval minimum advertisement interval (20 - 10240 ms)
|
||||||
|
* @param[in] max_interval maximum advertisement interval (20 - 10240 ms)
|
||||||
|
* @param[in] mac_type type of mac address (0x00 public, 0x01 static random)
|
||||||
|
* @param[in] mac_addr pointer to mac address
|
||||||
|
* @param[in] power_amp_level amplifier level (output dBm) (0x00 - 0x1F)
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool furi_hal_bt_custom_adv_start(
|
||||||
|
uint16_t min_interval,
|
||||||
|
uint16_t max_interval,
|
||||||
|
uint8_t mac_type,
|
||||||
|
const uint8_t mac_addr[GAP_MAC_ADDR_SIZE],
|
||||||
|
uint8_t power_amp_level);
|
||||||
|
|
||||||
|
/** Stop custom advertisement beacon
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool furi_hal_bt_custom_adv_stop();
|
||||||
|
|
||||||
void furi_hal_bt_set_profile_pairing_method(FuriHalBtProfile profile, GapPairing pairing_method);
|
void furi_hal_bt_set_profile_pairing_method(FuriHalBtProfile profile, GapPairing pairing_method);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user