177ba3d3fSMatthias Ringwald /* 277ba3d3fSMatthias Ringwald * Copyright (C) 2017 BlueKitchen GmbH 377ba3d3fSMatthias Ringwald * 477ba3d3fSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 577ba3d3fSMatthias Ringwald * modification, are permitted provided that the following conditions 677ba3d3fSMatthias Ringwald * are met: 777ba3d3fSMatthias Ringwald * 877ba3d3fSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 977ba3d3fSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 1077ba3d3fSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 1177ba3d3fSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 1277ba3d3fSMatthias Ringwald * documentation and/or other materials provided with the distribution. 1377ba3d3fSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 1477ba3d3fSMatthias Ringwald * contributors may be used to endorse or promote products derived 1577ba3d3fSMatthias Ringwald * from this software without specific prior written permission. 1677ba3d3fSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 1777ba3d3fSMatthias Ringwald * personal benefit and not for any commercial purpose or for 1877ba3d3fSMatthias Ringwald * monetary gain. 1977ba3d3fSMatthias Ringwald * 2077ba3d3fSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 2177ba3d3fSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2277ba3d3fSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2377ba3d3fSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 2477ba3d3fSMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2577ba3d3fSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2677ba3d3fSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 2777ba3d3fSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2877ba3d3fSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2977ba3d3fSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 3077ba3d3fSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3177ba3d3fSMatthias Ringwald * SUCH DAMAGE. 3277ba3d3fSMatthias Ringwald * 3377ba3d3fSMatthias Ringwald * Please inquire about commercial licensing options at 3477ba3d3fSMatthias Ringwald * [email protected] 3577ba3d3fSMatthias Ringwald * 3677ba3d3fSMatthias Ringwald */ 3777ba3d3fSMatthias Ringwald 3877ba3d3fSMatthias Ringwald #define __BTSTACK_FILE__ "adv_bearer.c" 3977ba3d3fSMatthias Ringwald 4077ba3d3fSMatthias Ringwald #define ENABLE_LOG_DEBUG 4177ba3d3fSMatthias Ringwald 4277ba3d3fSMatthias Ringwald #include <string.h> 4377ba3d3fSMatthias Ringwald 4477ba3d3fSMatthias Ringwald #include "mesh/adv_bearer.h" 4577ba3d3fSMatthias Ringwald #include "ble/core.h" 4677ba3d3fSMatthias Ringwald #include "bluetooth.h" 4777ba3d3fSMatthias Ringwald #include "bluetooth_data_types.h" 4877ba3d3fSMatthias Ringwald #include "btstack_debug.h" 4977ba3d3fSMatthias Ringwald #include "btstack_util.h" 5077ba3d3fSMatthias Ringwald #include "btstack_run_loop.h" 5177ba3d3fSMatthias Ringwald #include "btstack_event.h" 5277ba3d3fSMatthias Ringwald #include "gap.h" 5377ba3d3fSMatthias Ringwald 5477ba3d3fSMatthias Ringwald // issue: gap adv control in hci might be slow to update advertisements fast enough. for now add 10 ms extra to ADVERTISING_INTERVAL_CONNECTABLE_MIN_MS 5577ba3d3fSMatthias Ringwald // todo: track adv enable/disable events before next step 5677ba3d3fSMatthias Ringwald 5777ba3d3fSMatthias Ringwald // min advertising interval 20 ms for connectable advertisements 5877ba3d3fSMatthias Ringwald #define ADVERTISING_INTERVAL_CONNECTABLE_MIN 0x30 5977ba3d3fSMatthias Ringwald #define ADVERTISING_INTERVAL_CONNECTABLE_MIN_MS (ADVERTISING_INTERVAL_CONNECTABLE_MIN * 625 / 1000) 6077ba3d3fSMatthias Ringwald 6177ba3d3fSMatthias Ringwald // min advertising interval 100 ms for non-connectable advertisements (pre 5.0 controllers) 6277ba3d3fSMatthias Ringwald #define ADVERTISING_INTERVAL_NONCONNECTABLE_MIN 0xa0 6377ba3d3fSMatthias Ringwald #define ADVERTISING_INTERVAL_NONCONNECTABLE_MIN_MS (ADVERTISING_INTERVAL_NONCONNECTABLE_MIN * 625 / 1000) 6477ba3d3fSMatthias Ringwald 6577ba3d3fSMatthias Ringwald // num adv bearer message types 6677ba3d3fSMatthias Ringwald #define NUM_TYPES 3 6777ba3d3fSMatthias Ringwald 6877ba3d3fSMatthias Ringwald typedef enum { 6977ba3d3fSMatthias Ringwald MESH_NETWORK_ID, 7077ba3d3fSMatthias Ringwald MESH_BEACON_ID, 7177ba3d3fSMatthias Ringwald PB_ADV_ID, 7277ba3d3fSMatthias Ringwald INVALID_ID, 7377ba3d3fSMatthias Ringwald } message_type_id_t; 7477ba3d3fSMatthias Ringwald 7577ba3d3fSMatthias Ringwald typedef enum { 7677ba3d3fSMatthias Ringwald STATE_IDLE, 7777ba3d3fSMatthias Ringwald STATE_BEARER, 7877ba3d3fSMatthias Ringwald STATE_GAP, 7977ba3d3fSMatthias Ringwald } state_t; 8077ba3d3fSMatthias Ringwald 8177ba3d3fSMatthias Ringwald 8277ba3d3fSMatthias Ringwald // prototypes 8377ba3d3fSMatthias Ringwald static void adv_bearer_run(void); 8477ba3d3fSMatthias Ringwald 8577ba3d3fSMatthias Ringwald // globals 8677ba3d3fSMatthias Ringwald 8777ba3d3fSMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 8877ba3d3fSMatthias Ringwald static btstack_timer_source_t adv_timer; 8977ba3d3fSMatthias Ringwald static bd_addr_t null_addr; 9077ba3d3fSMatthias Ringwald 9177ba3d3fSMatthias Ringwald static btstack_packet_handler_t client_callbacks[NUM_TYPES]; 9277ba3d3fSMatthias Ringwald static int request_can_send_now[NUM_TYPES]; 9377ba3d3fSMatthias Ringwald static int last_sender; 9477ba3d3fSMatthias Ringwald 9577ba3d3fSMatthias Ringwald // scheduler 9677ba3d3fSMatthias Ringwald static state_t adv_bearer_state; 9777ba3d3fSMatthias Ringwald static uint32_t gap_adv_next_ms; 9877ba3d3fSMatthias Ringwald 9977ba3d3fSMatthias Ringwald // adv bearer packets 10077ba3d3fSMatthias Ringwald static uint8_t adv_bearer_buffer[31]; 10177ba3d3fSMatthias Ringwald static uint8_t adv_bearer_buffer_length; 10277ba3d3fSMatthias Ringwald static uint8_t adv_bearer_count; 10377ba3d3fSMatthias Ringwald static uint16_t adv_bearer_interval; 10477ba3d3fSMatthias Ringwald 10577ba3d3fSMatthias Ringwald // gap advertising 10677ba3d3fSMatthias Ringwald static int gap_advertising_enabled; 10777ba3d3fSMatthias Ringwald static uint16_t gap_adv_int_min = 0x30; 10877ba3d3fSMatthias Ringwald static uint16_t gap_adv_int_ms; 10977ba3d3fSMatthias Ringwald static uint16_t gap_adv_int_max = 0x30; 11077ba3d3fSMatthias Ringwald static uint8_t gap_adv_type = 0; 11177ba3d3fSMatthias Ringwald static uint8_t gap_direct_address_typ; 11277ba3d3fSMatthias Ringwald static bd_addr_t gap_direct_address; 11377ba3d3fSMatthias Ringwald static uint8_t gap_channel_map = 0x07; 11477ba3d3fSMatthias Ringwald static uint8_t gap_filter_policy = 0; 11577ba3d3fSMatthias Ringwald 11677ba3d3fSMatthias Ringwald static btstack_linked_list_t gap_connectable_advertisements; 11777ba3d3fSMatthias Ringwald 11877ba3d3fSMatthias Ringwald // dispatch advertising events 11977ba3d3fSMatthias Ringwald static void adv_bearer_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 12077ba3d3fSMatthias Ringwald const uint8_t * data; 12177ba3d3fSMatthias Ringwald int data_len; 12277ba3d3fSMatthias Ringwald message_type_id_t type_id; 12377ba3d3fSMatthias Ringwald 12477ba3d3fSMatthias Ringwald switch (packet_type){ 12577ba3d3fSMatthias Ringwald case HCI_EVENT_PACKET: 12677ba3d3fSMatthias Ringwald switch(packet[0]){ 12777ba3d3fSMatthias Ringwald case BTSTACK_EVENT_STATE: 12877ba3d3fSMatthias Ringwald if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; 12977ba3d3fSMatthias Ringwald adv_bearer_run(); 13077ba3d3fSMatthias Ringwald break; 13177ba3d3fSMatthias Ringwald case GAP_EVENT_ADVERTISING_REPORT: 13277ba3d3fSMatthias Ringwald // only non-connectable ind 13377ba3d3fSMatthias Ringwald if (gap_event_advertising_report_get_advertising_event_type(packet) != 0x03) break; 13477ba3d3fSMatthias Ringwald data = gap_event_advertising_report_get_data(packet); 13577ba3d3fSMatthias Ringwald data_len = gap_event_advertising_report_get_data_length(packet); 13677ba3d3fSMatthias Ringwald 13777ba3d3fSMatthias Ringwald switch(data[1]){ 13877ba3d3fSMatthias Ringwald case BLUETOOTH_DATA_TYPE_MESH_MESSAGE: 13977ba3d3fSMatthias Ringwald type_id = MESH_NETWORK_ID; 14077ba3d3fSMatthias Ringwald break; 14177ba3d3fSMatthias Ringwald case BLUETOOTH_DATA_TYPE_MESH_BEACON: 14277ba3d3fSMatthias Ringwald type_id = MESH_BEACON_ID; 14377ba3d3fSMatthias Ringwald break; 14477ba3d3fSMatthias Ringwald case BLUETOOTH_DATA_TYPE_PB_ADV: 14577ba3d3fSMatthias Ringwald type_id = PB_ADV_ID; 14677ba3d3fSMatthias Ringwald break; 14777ba3d3fSMatthias Ringwald default: 14877ba3d3fSMatthias Ringwald return; 14977ba3d3fSMatthias Ringwald } 15077ba3d3fSMatthias Ringwald if (client_callbacks[type_id]){ 15177ba3d3fSMatthias Ringwald switch (type_id){ 15277ba3d3fSMatthias Ringwald case PB_ADV_ID: 15377ba3d3fSMatthias Ringwald (*client_callbacks[type_id])(packet_type, channel, packet, size); 15477ba3d3fSMatthias Ringwald break; 15577ba3d3fSMatthias Ringwald case MESH_NETWORK_ID: 15677ba3d3fSMatthias Ringwald (*client_callbacks[type_id])(MESH_NETWORK_PACKET, 0, (uint8_t*) &data[2], data_len-2); 15777ba3d3fSMatthias Ringwald break; 15877ba3d3fSMatthias Ringwald case MESH_BEACON_ID: 15977ba3d3fSMatthias Ringwald (*client_callbacks[type_id])(MESH_BEACON_PACKET, 0, (uint8_t*) &data[2], data_len-2); 16077ba3d3fSMatthias Ringwald break; 16177ba3d3fSMatthias Ringwald default: 16277ba3d3fSMatthias Ringwald break; 16377ba3d3fSMatthias Ringwald } 16477ba3d3fSMatthias Ringwald } 16577ba3d3fSMatthias Ringwald break; 16677ba3d3fSMatthias Ringwald default: 16777ba3d3fSMatthias Ringwald break; 16877ba3d3fSMatthias Ringwald } 16977ba3d3fSMatthias Ringwald break; 17077ba3d3fSMatthias Ringwald default: 17177ba3d3fSMatthias Ringwald break; 17277ba3d3fSMatthias Ringwald } 17377ba3d3fSMatthias Ringwald } 17477ba3d3fSMatthias Ringwald 17577ba3d3fSMatthias Ringwald // round-robin 17677ba3d3fSMatthias Ringwald static void adv_bearer_emit_can_send_now(void){ 17777ba3d3fSMatthias Ringwald 17877ba3d3fSMatthias Ringwald if (adv_bearer_count > 0) return; 17977ba3d3fSMatthias Ringwald 18077ba3d3fSMatthias Ringwald int countdown = NUM_TYPES; 18177ba3d3fSMatthias Ringwald while (countdown--) { 18277ba3d3fSMatthias Ringwald last_sender++; 18377ba3d3fSMatthias Ringwald if (last_sender == NUM_TYPES) { 18477ba3d3fSMatthias Ringwald last_sender = 0; 18577ba3d3fSMatthias Ringwald } 18677ba3d3fSMatthias Ringwald if (request_can_send_now[last_sender]){ 18777ba3d3fSMatthias Ringwald request_can_send_now[last_sender] = 0; 18877ba3d3fSMatthias Ringwald // emit can send now 18977ba3d3fSMatthias Ringwald log_debug("can send now"); 19077ba3d3fSMatthias Ringwald uint8_t event[3]; 19177ba3d3fSMatthias Ringwald event[0] = HCI_EVENT_MESH_META; 19277ba3d3fSMatthias Ringwald event[1] = 1; 19377ba3d3fSMatthias Ringwald event[2] = MESH_SUBEVENT_CAN_SEND_NOW; 19477ba3d3fSMatthias Ringwald (*client_callbacks[last_sender])(HCI_EVENT_PACKET, 0, &event[0], sizeof(event)); 19577ba3d3fSMatthias Ringwald return; 19677ba3d3fSMatthias Ringwald } 19777ba3d3fSMatthias Ringwald } 19877ba3d3fSMatthias Ringwald } 19977ba3d3fSMatthias Ringwald 20077ba3d3fSMatthias Ringwald static void adv_bearer_timeout_handler(btstack_timer_source_t * ts){ 2012983fbcbSMatthias Ringwald UNUSED(ts); 20277ba3d3fSMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 20377ba3d3fSMatthias Ringwald switch (adv_bearer_state){ 20477ba3d3fSMatthias Ringwald case STATE_GAP: 20577ba3d3fSMatthias Ringwald log_debug("Timeout (state gap)"); 20677ba3d3fSMatthias Ringwald gap_advertisements_enable(0); 20777ba3d3fSMatthias Ringwald if (gap_advertising_enabled){ 20877ba3d3fSMatthias Ringwald gap_adv_next_ms = now + gap_adv_int_ms - ADVERTISING_INTERVAL_CONNECTABLE_MIN_MS; 20977ba3d3fSMatthias Ringwald log_debug("Next adv: %u", gap_adv_next_ms); 21077ba3d3fSMatthias Ringwald } 21177ba3d3fSMatthias Ringwald adv_bearer_state = STATE_IDLE; 21277ba3d3fSMatthias Ringwald break; 21377ba3d3fSMatthias Ringwald case STATE_BEARER: 21477ba3d3fSMatthias Ringwald log_debug("Timeout (state bearer)"); 21577ba3d3fSMatthias Ringwald gap_advertisements_enable(0); 21677ba3d3fSMatthias Ringwald adv_bearer_count--; 21777ba3d3fSMatthias Ringwald if (adv_bearer_count == 0){ 21877ba3d3fSMatthias Ringwald adv_bearer_emit_can_send_now(); 21977ba3d3fSMatthias Ringwald } 22077ba3d3fSMatthias Ringwald adv_bearer_state = STATE_IDLE; 22177ba3d3fSMatthias Ringwald break; 22277ba3d3fSMatthias Ringwald default: 22377ba3d3fSMatthias Ringwald break; 22477ba3d3fSMatthias Ringwald } 22577ba3d3fSMatthias Ringwald adv_bearer_run(); 22677ba3d3fSMatthias Ringwald } 22777ba3d3fSMatthias Ringwald 22877ba3d3fSMatthias Ringwald static void adv_bearer_set_timeout(uint32_t time_ms){ 22977ba3d3fSMatthias Ringwald btstack_run_loop_set_timer_handler(&adv_timer, &adv_bearer_timeout_handler); 23077ba3d3fSMatthias Ringwald btstack_run_loop_set_timer(&adv_timer, time_ms); // compile time constants 23177ba3d3fSMatthias Ringwald btstack_run_loop_add_timer(&adv_timer); 23277ba3d3fSMatthias Ringwald } 23377ba3d3fSMatthias Ringwald 23477ba3d3fSMatthias Ringwald // scheduler 23577ba3d3fSMatthias Ringwald static void adv_bearer_run(void){ 23677ba3d3fSMatthias Ringwald 23777ba3d3fSMatthias Ringwald if (hci_get_state() != HCI_STATE_WORKING) return; 23877ba3d3fSMatthias Ringwald 23977ba3d3fSMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 24077ba3d3fSMatthias Ringwald switch (adv_bearer_state){ 24177ba3d3fSMatthias Ringwald case STATE_IDLE: 24277ba3d3fSMatthias Ringwald if (gap_advertising_enabled){ 24377ba3d3fSMatthias Ringwald if ((int32_t)(now - gap_adv_next_ms) >= 0){ 24477ba3d3fSMatthias Ringwald adv_bearer_connectable_advertisement_data_item_t * item = (adv_bearer_connectable_advertisement_data_item_t *) btstack_linked_list_pop(&gap_connectable_advertisements); 24577ba3d3fSMatthias Ringwald if (item != NULL){ 24677ba3d3fSMatthias Ringwald // queue again 24777ba3d3fSMatthias Ringwald btstack_linked_list_add_tail(&gap_connectable_advertisements, (void*) item); 24877ba3d3fSMatthias Ringwald // time to advertise again 24977ba3d3fSMatthias Ringwald log_debug("Start GAP ADV, %p", item); 25077ba3d3fSMatthias Ringwald gap_advertisements_set_params(ADVERTISING_INTERVAL_CONNECTABLE_MIN, ADVERTISING_INTERVAL_CONNECTABLE_MIN, gap_adv_type, gap_direct_address_typ, gap_direct_address, gap_channel_map, gap_filter_policy); 25177ba3d3fSMatthias Ringwald gap_advertisements_set_data(item->adv_length, item->adv_data); 25277ba3d3fSMatthias Ringwald gap_advertisements_enable(1); 25377ba3d3fSMatthias Ringwald adv_bearer_set_timeout(ADVERTISING_INTERVAL_CONNECTABLE_MIN_MS); 25477ba3d3fSMatthias Ringwald adv_bearer_state = STATE_GAP; 25577ba3d3fSMatthias Ringwald } 25677ba3d3fSMatthias Ringwald break; 25777ba3d3fSMatthias Ringwald } 25877ba3d3fSMatthias Ringwald } 25977ba3d3fSMatthias Ringwald if (adv_bearer_count > 0){ 26077ba3d3fSMatthias Ringwald // schedule adv bearer message if enough time 26177ba3d3fSMatthias Ringwald // if ((gap_advertising_enabled) == 0 || ((int32_t)(gap_adv_next_ms - now) >= ADVERTISING_INTERVAL_NONCONNECTABLE_MIN_MS)){ 26277ba3d3fSMatthias Ringwald log_debug("Send ADV Bearer message"); 26377ba3d3fSMatthias Ringwald // configure LE advertisments: non-conn ind 26477ba3d3fSMatthias Ringwald gap_advertisements_set_params(ADVERTISING_INTERVAL_NONCONNECTABLE_MIN, ADVERTISING_INTERVAL_NONCONNECTABLE_MIN, 3, 0, null_addr, 0x07, 0); 26577ba3d3fSMatthias Ringwald gap_advertisements_set_data(adv_bearer_buffer_length, adv_bearer_buffer); 26677ba3d3fSMatthias Ringwald gap_advertisements_enable(1); 26777ba3d3fSMatthias Ringwald adv_bearer_set_timeout(ADVERTISING_INTERVAL_NONCONNECTABLE_MIN_MS); 26877ba3d3fSMatthias Ringwald adv_bearer_state = STATE_BEARER; 26977ba3d3fSMatthias Ringwald break; 27077ba3d3fSMatthias Ringwald // } 27177ba3d3fSMatthias Ringwald } 27277ba3d3fSMatthias Ringwald if (gap_advertising_enabled){ 27377ba3d3fSMatthias Ringwald // use timer to wait for next adv 27477ba3d3fSMatthias Ringwald adv_bearer_set_timeout(gap_adv_next_ms - now); 27577ba3d3fSMatthias Ringwald } 27677ba3d3fSMatthias Ringwald break; 27777ba3d3fSMatthias Ringwald default: 27877ba3d3fSMatthias Ringwald break; 27977ba3d3fSMatthias Ringwald } 28077ba3d3fSMatthias Ringwald } 28177ba3d3fSMatthias Ringwald 28277ba3d3fSMatthias Ringwald // 283*3bf10e3aSMatthias Ringwald static void adv_bearer_prepare_message(const uint8_t * data, uint16_t data_len, uint8_t type, uint8_t count, uint16_t interval){ 28477ba3d3fSMatthias Ringwald log_debug("adv bearer message, type 0x%x\n", type); 28577ba3d3fSMatthias Ringwald // prepare message 28677ba3d3fSMatthias Ringwald adv_bearer_buffer[0] = data_len+1; 28777ba3d3fSMatthias Ringwald adv_bearer_buffer[1] = type; 28877ba3d3fSMatthias Ringwald memcpy(&adv_bearer_buffer[2], data, data_len); 28977ba3d3fSMatthias Ringwald adv_bearer_buffer_length = data_len + 2; 29077ba3d3fSMatthias Ringwald 291*3bf10e3aSMatthias Ringwald // setup trasmission schedule 292*3bf10e3aSMatthias Ringwald adv_bearer_count = count; 293*3bf10e3aSMatthias Ringwald adv_bearer_interval = interval; 29477ba3d3fSMatthias Ringwald } 29577ba3d3fSMatthias Ringwald 29677ba3d3fSMatthias Ringwald ////// 29777ba3d3fSMatthias Ringwald 29877ba3d3fSMatthias Ringwald static void adv_bearer_request(message_type_id_t type_id){ 29977ba3d3fSMatthias Ringwald request_can_send_now[type_id] = 1; 30077ba3d3fSMatthias Ringwald adv_bearer_emit_can_send_now(); 30177ba3d3fSMatthias Ringwald } 30277ba3d3fSMatthias Ringwald 30377ba3d3fSMatthias Ringwald void adv_bearer_init(void){ 30477ba3d3fSMatthias Ringwald // register for HCI Events 30577ba3d3fSMatthias Ringwald hci_event_callback_registration.callback = &adv_bearer_packet_handler; 30677ba3d3fSMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 30777ba3d3fSMatthias Ringwald // idle 30877ba3d3fSMatthias Ringwald adv_bearer_state = STATE_IDLE; 30977ba3d3fSMatthias Ringwald memset(null_addr, 0, 6); 31077ba3d3fSMatthias Ringwald } 31177ba3d3fSMatthias Ringwald 31277ba3d3fSMatthias Ringwald // adv bearer packet handler regisration 31377ba3d3fSMatthias Ringwald 3144662af4aSMatthias Ringwald void adv_bearer_register_for_network_pdu(btstack_packet_handler_t packet_handler){ 31577ba3d3fSMatthias Ringwald client_callbacks[MESH_NETWORK_ID] = packet_handler; 31677ba3d3fSMatthias Ringwald } 3174662af4aSMatthias Ringwald void adv_bearer_register_for_beacon(btstack_packet_handler_t packet_handler){ 31877ba3d3fSMatthias Ringwald client_callbacks[MESH_BEACON_ID] = packet_handler; 31977ba3d3fSMatthias Ringwald } 3204662af4aSMatthias Ringwald void adv_bearer_register_for_provisioning_pdu(btstack_packet_handler_t packet_handler){ 32177ba3d3fSMatthias Ringwald client_callbacks[PB_ADV_ID] = packet_handler; 32277ba3d3fSMatthias Ringwald } 32377ba3d3fSMatthias Ringwald 32477ba3d3fSMatthias Ringwald // adv bearer request to send 32577ba3d3fSMatthias Ringwald 3264662af4aSMatthias Ringwald void adv_bearer_request_can_send_now_for_network_pdu(void){ 32777ba3d3fSMatthias Ringwald adv_bearer_request(MESH_NETWORK_ID); 32877ba3d3fSMatthias Ringwald } 3294662af4aSMatthias Ringwald void adv_bearer_request_can_send_now_for_beacon(void){ 33077ba3d3fSMatthias Ringwald adv_bearer_request(MESH_BEACON_ID); 33177ba3d3fSMatthias Ringwald } 3324662af4aSMatthias Ringwald void adv_bearer_request_can_send_now_for_provisioning_pdu(void){ 33377ba3d3fSMatthias Ringwald adv_bearer_request(PB_ADV_ID); 33477ba3d3fSMatthias Ringwald } 33577ba3d3fSMatthias Ringwald 33677ba3d3fSMatthias Ringwald // adv bearer send message 33777ba3d3fSMatthias Ringwald 338*3bf10e3aSMatthias Ringwald void adv_bearer_send_network_pdu(const uint8_t * data, uint16_t data_len, uint8_t count, uint16_t interval){ 339*3bf10e3aSMatthias Ringwald adv_bearer_prepare_message(data, data_len, BLUETOOTH_DATA_TYPE_MESH_MESSAGE, count, interval); 34077ba3d3fSMatthias Ringwald adv_bearer_run(); 34177ba3d3fSMatthias Ringwald } 3424662af4aSMatthias Ringwald void adv_bearer_send_beacon(const uint8_t * data, uint16_t data_len){ 343*3bf10e3aSMatthias Ringwald adv_bearer_prepare_message(data, data_len, BLUETOOTH_DATA_TYPE_MESH_BEACON, 3, 100); 34477ba3d3fSMatthias Ringwald adv_bearer_run(); 34577ba3d3fSMatthias Ringwald } 3464662af4aSMatthias Ringwald void adv_bearer_send_provisioning_pdu(const uint8_t * data, uint16_t data_len){ 347*3bf10e3aSMatthias Ringwald adv_bearer_prepare_message(data, data_len, BLUETOOTH_DATA_TYPE_PB_ADV, 3, 100); 34877ba3d3fSMatthias Ringwald adv_bearer_run(); 34977ba3d3fSMatthias Ringwald } 35077ba3d3fSMatthias Ringwald 35177ba3d3fSMatthias Ringwald // gap advertising 35277ba3d3fSMatthias Ringwald 35377ba3d3fSMatthias Ringwald void adv_bearer_advertisements_enable(int enabled){ 35477ba3d3fSMatthias Ringwald gap_advertising_enabled = enabled; 35577ba3d3fSMatthias Ringwald if (!gap_advertising_enabled) return; 35677ba3d3fSMatthias Ringwald 35777ba3d3fSMatthias Ringwald // start right away 35877ba3d3fSMatthias Ringwald gap_adv_next_ms = btstack_run_loop_get_time_ms(); 35977ba3d3fSMatthias Ringwald adv_bearer_run(); 36077ba3d3fSMatthias Ringwald } 36177ba3d3fSMatthias Ringwald 36277ba3d3fSMatthias Ringwald void adv_bearer_advertisements_add_item(adv_bearer_connectable_advertisement_data_item_t * item){ 36377ba3d3fSMatthias Ringwald btstack_linked_list_add(&gap_connectable_advertisements, (void*) item); 36477ba3d3fSMatthias Ringwald } 36577ba3d3fSMatthias Ringwald 36677ba3d3fSMatthias Ringwald void adv_bearer_advertisements_remove_item(adv_bearer_connectable_advertisement_data_item_t * item){ 36777ba3d3fSMatthias Ringwald btstack_linked_list_remove(&gap_connectable_advertisements, (void*) item); 36877ba3d3fSMatthias Ringwald } 36977ba3d3fSMatthias Ringwald 37077ba3d3fSMatthias Ringwald void adv_bearer_advertisements_set_params(uint16_t adv_int_min, uint16_t adv_int_max, uint8_t adv_type, 37177ba3d3fSMatthias Ringwald uint8_t direct_address_typ, bd_addr_t direct_address, uint8_t channel_map, uint8_t filter_policy){ 37277ba3d3fSMatthias Ringwald 37377ba3d3fSMatthias Ringwald // assert adv_int_min/max >= 2 * ADVERTISING_INTERVAL_MIN 37477ba3d3fSMatthias Ringwald 37577ba3d3fSMatthias Ringwald gap_adv_int_min = btstack_max(adv_int_min, 2 * ADVERTISING_INTERVAL_CONNECTABLE_MIN); 37677ba3d3fSMatthias Ringwald gap_adv_int_max = btstack_max(adv_int_max, 2 * ADVERTISING_INTERVAL_CONNECTABLE_MIN); 37777ba3d3fSMatthias Ringwald gap_adv_int_ms = gap_adv_int_min * 625 / 1000; 37877ba3d3fSMatthias Ringwald gap_adv_type = adv_type; 37977ba3d3fSMatthias Ringwald gap_direct_address_typ = direct_address_typ; 38077ba3d3fSMatthias Ringwald memcpy(gap_direct_address, &direct_address, 6); 38177ba3d3fSMatthias Ringwald gap_channel_map = channel_map; 38277ba3d3fSMatthias Ringwald gap_filter_policy = filter_policy; 38377ba3d3fSMatthias Ringwald 38477ba3d3fSMatthias Ringwald log_info("GAP Adv interval %u ms", gap_adv_int_ms); 38577ba3d3fSMatthias Ringwald } 386