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 38*2d4000d1SMatthias 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; 8920cc5daeSMatthias Ringwald static int adv_timer_active; 9077ba3d3fSMatthias Ringwald static bd_addr_t null_addr; 9177ba3d3fSMatthias Ringwald 9277ba3d3fSMatthias Ringwald static btstack_packet_handler_t client_callbacks[NUM_TYPES]; 9377ba3d3fSMatthias Ringwald static int request_can_send_now[NUM_TYPES]; 9477ba3d3fSMatthias Ringwald static int last_sender; 9577ba3d3fSMatthias Ringwald 9677ba3d3fSMatthias Ringwald // scheduler 9777ba3d3fSMatthias Ringwald static state_t adv_bearer_state; 9877ba3d3fSMatthias Ringwald static uint32_t gap_adv_next_ms; 9977ba3d3fSMatthias Ringwald 10077ba3d3fSMatthias Ringwald // adv bearer packets 10177ba3d3fSMatthias Ringwald static uint8_t adv_bearer_buffer[31]; 10277ba3d3fSMatthias Ringwald static uint8_t adv_bearer_buffer_length; 10377ba3d3fSMatthias Ringwald static uint8_t adv_bearer_count; 10477ba3d3fSMatthias Ringwald static uint16_t adv_bearer_interval; 10577ba3d3fSMatthias Ringwald 10677ba3d3fSMatthias Ringwald // gap advertising 10777ba3d3fSMatthias Ringwald static int gap_advertising_enabled; 10877ba3d3fSMatthias Ringwald static uint16_t gap_adv_int_min = 0x30; 10977ba3d3fSMatthias Ringwald static uint16_t gap_adv_int_ms; 11077ba3d3fSMatthias Ringwald static uint16_t gap_adv_int_max = 0x30; 11177ba3d3fSMatthias Ringwald static uint8_t gap_adv_type = 0; 11277ba3d3fSMatthias Ringwald static uint8_t gap_direct_address_typ; 11377ba3d3fSMatthias Ringwald static bd_addr_t gap_direct_address; 11477ba3d3fSMatthias Ringwald static uint8_t gap_channel_map = 0x07; 11577ba3d3fSMatthias Ringwald static uint8_t gap_filter_policy = 0; 11677ba3d3fSMatthias Ringwald 11777ba3d3fSMatthias Ringwald static btstack_linked_list_t gap_connectable_advertisements; 11877ba3d3fSMatthias Ringwald 11977ba3d3fSMatthias Ringwald // dispatch advertising events 12077ba3d3fSMatthias Ringwald static void adv_bearer_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 12177ba3d3fSMatthias Ringwald const uint8_t * data; 12277ba3d3fSMatthias Ringwald int data_len; 12377ba3d3fSMatthias Ringwald message_type_id_t type_id; 12477ba3d3fSMatthias Ringwald 12577ba3d3fSMatthias Ringwald switch (packet_type){ 12677ba3d3fSMatthias Ringwald case HCI_EVENT_PACKET: 12777ba3d3fSMatthias Ringwald switch(packet[0]){ 12877ba3d3fSMatthias Ringwald case BTSTACK_EVENT_STATE: 12977ba3d3fSMatthias Ringwald if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; 13077ba3d3fSMatthias Ringwald adv_bearer_run(); 13177ba3d3fSMatthias Ringwald break; 13277ba3d3fSMatthias Ringwald case GAP_EVENT_ADVERTISING_REPORT: 13377ba3d3fSMatthias Ringwald // only non-connectable ind 13477ba3d3fSMatthias Ringwald if (gap_event_advertising_report_get_advertising_event_type(packet) != 0x03) break; 13577ba3d3fSMatthias Ringwald data = gap_event_advertising_report_get_data(packet); 13677ba3d3fSMatthias Ringwald data_len = gap_event_advertising_report_get_data_length(packet); 13777ba3d3fSMatthias Ringwald 13877ba3d3fSMatthias Ringwald switch(data[1]){ 13977ba3d3fSMatthias Ringwald case BLUETOOTH_DATA_TYPE_MESH_MESSAGE: 14077ba3d3fSMatthias Ringwald type_id = MESH_NETWORK_ID; 14177ba3d3fSMatthias Ringwald break; 14277ba3d3fSMatthias Ringwald case BLUETOOTH_DATA_TYPE_MESH_BEACON: 14377ba3d3fSMatthias Ringwald type_id = MESH_BEACON_ID; 14477ba3d3fSMatthias Ringwald break; 14577ba3d3fSMatthias Ringwald case BLUETOOTH_DATA_TYPE_PB_ADV: 14677ba3d3fSMatthias Ringwald type_id = PB_ADV_ID; 14777ba3d3fSMatthias Ringwald break; 14877ba3d3fSMatthias Ringwald default: 14977ba3d3fSMatthias Ringwald return; 15077ba3d3fSMatthias Ringwald } 15177ba3d3fSMatthias Ringwald if (client_callbacks[type_id]){ 15277ba3d3fSMatthias Ringwald switch (type_id){ 15377ba3d3fSMatthias Ringwald case PB_ADV_ID: 15477ba3d3fSMatthias Ringwald (*client_callbacks[type_id])(packet_type, channel, packet, size); 15577ba3d3fSMatthias Ringwald break; 15677ba3d3fSMatthias Ringwald case MESH_NETWORK_ID: 15777ba3d3fSMatthias Ringwald (*client_callbacks[type_id])(MESH_NETWORK_PACKET, 0, (uint8_t*) &data[2], data_len-2); 15877ba3d3fSMatthias Ringwald break; 15977ba3d3fSMatthias Ringwald case MESH_BEACON_ID: 16077ba3d3fSMatthias Ringwald (*client_callbacks[type_id])(MESH_BEACON_PACKET, 0, (uint8_t*) &data[2], data_len-2); 16177ba3d3fSMatthias Ringwald break; 16277ba3d3fSMatthias Ringwald default: 16377ba3d3fSMatthias Ringwald break; 16477ba3d3fSMatthias Ringwald } 16577ba3d3fSMatthias Ringwald } 16677ba3d3fSMatthias Ringwald break; 16777ba3d3fSMatthias Ringwald default: 16877ba3d3fSMatthias Ringwald break; 16977ba3d3fSMatthias Ringwald } 17077ba3d3fSMatthias Ringwald break; 17177ba3d3fSMatthias Ringwald default: 17277ba3d3fSMatthias Ringwald break; 17377ba3d3fSMatthias Ringwald } 17477ba3d3fSMatthias Ringwald } 17577ba3d3fSMatthias Ringwald 17677ba3d3fSMatthias Ringwald // round-robin 17777ba3d3fSMatthias Ringwald static void adv_bearer_emit_can_send_now(void){ 17877ba3d3fSMatthias Ringwald 17977ba3d3fSMatthias Ringwald if (adv_bearer_count > 0) return; 18077ba3d3fSMatthias Ringwald 18177ba3d3fSMatthias Ringwald int countdown = NUM_TYPES; 18277ba3d3fSMatthias Ringwald while (countdown--) { 18377ba3d3fSMatthias Ringwald last_sender++; 18477ba3d3fSMatthias Ringwald if (last_sender == NUM_TYPES) { 18577ba3d3fSMatthias Ringwald last_sender = 0; 18677ba3d3fSMatthias Ringwald } 18777ba3d3fSMatthias Ringwald if (request_can_send_now[last_sender]){ 18877ba3d3fSMatthias Ringwald request_can_send_now[last_sender] = 0; 18977ba3d3fSMatthias Ringwald // emit can send now 19077ba3d3fSMatthias Ringwald log_debug("can send now"); 19177ba3d3fSMatthias Ringwald uint8_t event[3]; 19277ba3d3fSMatthias Ringwald event[0] = HCI_EVENT_MESH_META; 19377ba3d3fSMatthias Ringwald event[1] = 1; 19477ba3d3fSMatthias Ringwald event[2] = MESH_SUBEVENT_CAN_SEND_NOW; 19577ba3d3fSMatthias Ringwald (*client_callbacks[last_sender])(HCI_EVENT_PACKET, 0, &event[0], sizeof(event)); 19677ba3d3fSMatthias Ringwald return; 19777ba3d3fSMatthias Ringwald } 19877ba3d3fSMatthias Ringwald } 19977ba3d3fSMatthias Ringwald } 20077ba3d3fSMatthias Ringwald 20177ba3d3fSMatthias Ringwald static void adv_bearer_timeout_handler(btstack_timer_source_t * ts){ 2022983fbcbSMatthias Ringwald UNUSED(ts); 20320cc5daeSMatthias Ringwald adv_timer_active = 0; 20477ba3d3fSMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 20577ba3d3fSMatthias Ringwald switch (adv_bearer_state){ 20677ba3d3fSMatthias Ringwald case STATE_GAP: 20777ba3d3fSMatthias Ringwald log_debug("Timeout (state gap)"); 20877ba3d3fSMatthias Ringwald gap_advertisements_enable(0); 20977ba3d3fSMatthias Ringwald if (gap_advertising_enabled){ 21077ba3d3fSMatthias Ringwald gap_adv_next_ms = now + gap_adv_int_ms - ADVERTISING_INTERVAL_CONNECTABLE_MIN_MS; 21177ba3d3fSMatthias Ringwald log_debug("Next adv: %u", gap_adv_next_ms); 21277ba3d3fSMatthias Ringwald } 21377ba3d3fSMatthias Ringwald adv_bearer_state = STATE_IDLE; 21477ba3d3fSMatthias Ringwald break; 21577ba3d3fSMatthias Ringwald case STATE_BEARER: 21677ba3d3fSMatthias Ringwald log_debug("Timeout (state bearer)"); 21777ba3d3fSMatthias Ringwald gap_advertisements_enable(0); 21877ba3d3fSMatthias Ringwald adv_bearer_count--; 21977ba3d3fSMatthias Ringwald if (adv_bearer_count == 0){ 22077ba3d3fSMatthias Ringwald adv_bearer_emit_can_send_now(); 22177ba3d3fSMatthias Ringwald } 22277ba3d3fSMatthias Ringwald adv_bearer_state = STATE_IDLE; 22377ba3d3fSMatthias Ringwald break; 22477ba3d3fSMatthias Ringwald default: 22577ba3d3fSMatthias Ringwald break; 22677ba3d3fSMatthias Ringwald } 22777ba3d3fSMatthias Ringwald adv_bearer_run(); 22877ba3d3fSMatthias Ringwald } 22977ba3d3fSMatthias Ringwald 23077ba3d3fSMatthias Ringwald static void adv_bearer_set_timeout(uint32_t time_ms){ 23177ba3d3fSMatthias Ringwald btstack_run_loop_set_timer_handler(&adv_timer, &adv_bearer_timeout_handler); 23277ba3d3fSMatthias Ringwald btstack_run_loop_set_timer(&adv_timer, time_ms); // compile time constants 23377ba3d3fSMatthias Ringwald btstack_run_loop_add_timer(&adv_timer); 23420cc5daeSMatthias Ringwald adv_timer_active = 1; 23577ba3d3fSMatthias Ringwald } 23677ba3d3fSMatthias Ringwald 23777ba3d3fSMatthias Ringwald // scheduler 23877ba3d3fSMatthias Ringwald static void adv_bearer_run(void){ 23977ba3d3fSMatthias Ringwald 24077ba3d3fSMatthias Ringwald if (hci_get_state() != HCI_STATE_WORKING) return; 24120cc5daeSMatthias Ringwald if (adv_timer_active) return; 24277ba3d3fSMatthias Ringwald 24377ba3d3fSMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 24477ba3d3fSMatthias Ringwald switch (adv_bearer_state){ 24577ba3d3fSMatthias Ringwald case STATE_IDLE: 24677ba3d3fSMatthias Ringwald if (gap_advertising_enabled){ 24777ba3d3fSMatthias Ringwald if ((int32_t)(now - gap_adv_next_ms) >= 0){ 24877ba3d3fSMatthias Ringwald adv_bearer_connectable_advertisement_data_item_t * item = (adv_bearer_connectable_advertisement_data_item_t *) btstack_linked_list_pop(&gap_connectable_advertisements); 24977ba3d3fSMatthias Ringwald if (item != NULL){ 25077ba3d3fSMatthias Ringwald // queue again 25177ba3d3fSMatthias Ringwald btstack_linked_list_add_tail(&gap_connectable_advertisements, (void*) item); 25277ba3d3fSMatthias Ringwald // time to advertise again 25377ba3d3fSMatthias Ringwald log_debug("Start GAP ADV, %p", item); 25477ba3d3fSMatthias 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); 25577ba3d3fSMatthias Ringwald gap_advertisements_set_data(item->adv_length, item->adv_data); 25677ba3d3fSMatthias Ringwald gap_advertisements_enable(1); 25777ba3d3fSMatthias Ringwald adv_bearer_state = STATE_GAP; 25820cc5daeSMatthias Ringwald adv_bearer_set_timeout(ADVERTISING_INTERVAL_CONNECTABLE_MIN_MS); 25977ba3d3fSMatthias Ringwald } 26077ba3d3fSMatthias Ringwald break; 26177ba3d3fSMatthias Ringwald } 26277ba3d3fSMatthias Ringwald } 26377ba3d3fSMatthias Ringwald if (adv_bearer_count > 0){ 26477ba3d3fSMatthias Ringwald // schedule adv bearer message if enough time 26577ba3d3fSMatthias Ringwald // if ((gap_advertising_enabled) == 0 || ((int32_t)(gap_adv_next_ms - now) >= ADVERTISING_INTERVAL_NONCONNECTABLE_MIN_MS)){ 26677ba3d3fSMatthias Ringwald log_debug("Send ADV Bearer message"); 26777ba3d3fSMatthias Ringwald // configure LE advertisments: non-conn ind 26877ba3d3fSMatthias Ringwald gap_advertisements_set_params(ADVERTISING_INTERVAL_NONCONNECTABLE_MIN, ADVERTISING_INTERVAL_NONCONNECTABLE_MIN, 3, 0, null_addr, 0x07, 0); 26977ba3d3fSMatthias Ringwald gap_advertisements_set_data(adv_bearer_buffer_length, adv_bearer_buffer); 27077ba3d3fSMatthias Ringwald gap_advertisements_enable(1); 27177ba3d3fSMatthias Ringwald adv_bearer_state = STATE_BEARER; 27220cc5daeSMatthias Ringwald adv_bearer_set_timeout(ADVERTISING_INTERVAL_NONCONNECTABLE_MIN_MS); 27377ba3d3fSMatthias Ringwald break; 27477ba3d3fSMatthias Ringwald // } 27577ba3d3fSMatthias Ringwald } 27677ba3d3fSMatthias Ringwald if (gap_advertising_enabled){ 27777ba3d3fSMatthias Ringwald // use timer to wait for next adv 27877ba3d3fSMatthias Ringwald adv_bearer_set_timeout(gap_adv_next_ms - now); 27977ba3d3fSMatthias Ringwald } 28077ba3d3fSMatthias Ringwald break; 28177ba3d3fSMatthias Ringwald default: 28277ba3d3fSMatthias Ringwald break; 28377ba3d3fSMatthias Ringwald } 28477ba3d3fSMatthias Ringwald } 28577ba3d3fSMatthias Ringwald 28677ba3d3fSMatthias Ringwald // 2873bf10e3aSMatthias Ringwald static void adv_bearer_prepare_message(const uint8_t * data, uint16_t data_len, uint8_t type, uint8_t count, uint16_t interval){ 288e529392eSMatthias Ringwald btstack_assert(data_len <= (sizeof(adv_bearer_buffer)-2)); 28977ba3d3fSMatthias Ringwald log_debug("adv bearer message, type 0x%x\n", type); 29077ba3d3fSMatthias Ringwald // prepare message 29177ba3d3fSMatthias Ringwald adv_bearer_buffer[0] = data_len+1; 29277ba3d3fSMatthias Ringwald adv_bearer_buffer[1] = type; 29377ba3d3fSMatthias Ringwald memcpy(&adv_bearer_buffer[2], data, data_len); 29477ba3d3fSMatthias Ringwald adv_bearer_buffer_length = data_len + 2; 29577ba3d3fSMatthias Ringwald 2963bf10e3aSMatthias Ringwald // setup trasmission schedule 2973bf10e3aSMatthias Ringwald adv_bearer_count = count; 2983bf10e3aSMatthias Ringwald adv_bearer_interval = interval; 29977ba3d3fSMatthias Ringwald } 30077ba3d3fSMatthias Ringwald 30177ba3d3fSMatthias Ringwald ////// 30277ba3d3fSMatthias Ringwald 30377ba3d3fSMatthias Ringwald static void adv_bearer_request(message_type_id_t type_id){ 30477ba3d3fSMatthias Ringwald request_can_send_now[type_id] = 1; 30577ba3d3fSMatthias Ringwald adv_bearer_emit_can_send_now(); 30677ba3d3fSMatthias Ringwald } 30777ba3d3fSMatthias Ringwald 30877ba3d3fSMatthias Ringwald void adv_bearer_init(void){ 30977ba3d3fSMatthias Ringwald // register for HCI Events 31077ba3d3fSMatthias Ringwald hci_event_callback_registration.callback = &adv_bearer_packet_handler; 31177ba3d3fSMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 31277ba3d3fSMatthias Ringwald // idle 31377ba3d3fSMatthias Ringwald adv_bearer_state = STATE_IDLE; 31477ba3d3fSMatthias Ringwald memset(null_addr, 0, 6); 31577ba3d3fSMatthias Ringwald } 31677ba3d3fSMatthias Ringwald 31777ba3d3fSMatthias Ringwald // adv bearer packet handler regisration 31877ba3d3fSMatthias Ringwald 3194662af4aSMatthias Ringwald void adv_bearer_register_for_network_pdu(btstack_packet_handler_t packet_handler){ 32077ba3d3fSMatthias Ringwald client_callbacks[MESH_NETWORK_ID] = packet_handler; 32177ba3d3fSMatthias Ringwald } 3224662af4aSMatthias Ringwald void adv_bearer_register_for_beacon(btstack_packet_handler_t packet_handler){ 32377ba3d3fSMatthias Ringwald client_callbacks[MESH_BEACON_ID] = packet_handler; 32477ba3d3fSMatthias Ringwald } 3254662af4aSMatthias Ringwald void adv_bearer_register_for_provisioning_pdu(btstack_packet_handler_t packet_handler){ 32677ba3d3fSMatthias Ringwald client_callbacks[PB_ADV_ID] = packet_handler; 32777ba3d3fSMatthias Ringwald } 32877ba3d3fSMatthias Ringwald 32977ba3d3fSMatthias Ringwald // adv bearer request to send 33077ba3d3fSMatthias Ringwald 3314662af4aSMatthias Ringwald void adv_bearer_request_can_send_now_for_network_pdu(void){ 33277ba3d3fSMatthias Ringwald adv_bearer_request(MESH_NETWORK_ID); 33377ba3d3fSMatthias Ringwald } 3344662af4aSMatthias Ringwald void adv_bearer_request_can_send_now_for_beacon(void){ 33577ba3d3fSMatthias Ringwald adv_bearer_request(MESH_BEACON_ID); 33677ba3d3fSMatthias Ringwald } 3374662af4aSMatthias Ringwald void adv_bearer_request_can_send_now_for_provisioning_pdu(void){ 33877ba3d3fSMatthias Ringwald adv_bearer_request(PB_ADV_ID); 33977ba3d3fSMatthias Ringwald } 34077ba3d3fSMatthias Ringwald 34177ba3d3fSMatthias Ringwald // adv bearer send message 34277ba3d3fSMatthias Ringwald 3433bf10e3aSMatthias Ringwald void adv_bearer_send_network_pdu(const uint8_t * data, uint16_t data_len, uint8_t count, uint16_t interval){ 344e529392eSMatthias Ringwald btstack_assert(data_len <= (sizeof(adv_bearer_buffer)-2)); 3453bf10e3aSMatthias Ringwald adv_bearer_prepare_message(data, data_len, BLUETOOTH_DATA_TYPE_MESH_MESSAGE, count, interval); 34677ba3d3fSMatthias Ringwald adv_bearer_run(); 34777ba3d3fSMatthias Ringwald } 3484662af4aSMatthias Ringwald void adv_bearer_send_beacon(const uint8_t * data, uint16_t data_len){ 349e529392eSMatthias Ringwald btstack_assert(data_len <= (sizeof(adv_bearer_buffer)-2)); 3503bf10e3aSMatthias Ringwald adv_bearer_prepare_message(data, data_len, BLUETOOTH_DATA_TYPE_MESH_BEACON, 3, 100); 35177ba3d3fSMatthias Ringwald adv_bearer_run(); 35277ba3d3fSMatthias Ringwald } 3534662af4aSMatthias Ringwald void adv_bearer_send_provisioning_pdu(const uint8_t * data, uint16_t data_len){ 354e529392eSMatthias Ringwald btstack_assert(data_len <= (sizeof(adv_bearer_buffer)-2)); 3553bf10e3aSMatthias Ringwald adv_bearer_prepare_message(data, data_len, BLUETOOTH_DATA_TYPE_PB_ADV, 3, 100); 35677ba3d3fSMatthias Ringwald adv_bearer_run(); 35777ba3d3fSMatthias Ringwald } 35877ba3d3fSMatthias Ringwald 35977ba3d3fSMatthias Ringwald // gap advertising 36077ba3d3fSMatthias Ringwald 36177ba3d3fSMatthias Ringwald void adv_bearer_advertisements_enable(int enabled){ 36277ba3d3fSMatthias Ringwald gap_advertising_enabled = enabled; 36377ba3d3fSMatthias Ringwald if (!gap_advertising_enabled) return; 36477ba3d3fSMatthias Ringwald 36577ba3d3fSMatthias Ringwald // start right away 36677ba3d3fSMatthias Ringwald gap_adv_next_ms = btstack_run_loop_get_time_ms(); 36777ba3d3fSMatthias Ringwald adv_bearer_run(); 36877ba3d3fSMatthias Ringwald } 36977ba3d3fSMatthias Ringwald 37077ba3d3fSMatthias Ringwald void adv_bearer_advertisements_add_item(adv_bearer_connectable_advertisement_data_item_t * item){ 37177ba3d3fSMatthias Ringwald btstack_linked_list_add(&gap_connectable_advertisements, (void*) item); 37277ba3d3fSMatthias Ringwald } 37377ba3d3fSMatthias Ringwald 37477ba3d3fSMatthias Ringwald void adv_bearer_advertisements_remove_item(adv_bearer_connectable_advertisement_data_item_t * item){ 37577ba3d3fSMatthias Ringwald btstack_linked_list_remove(&gap_connectable_advertisements, (void*) item); 37677ba3d3fSMatthias Ringwald } 37777ba3d3fSMatthias Ringwald 37877ba3d3fSMatthias Ringwald void adv_bearer_advertisements_set_params(uint16_t adv_int_min, uint16_t adv_int_max, uint8_t adv_type, 37977ba3d3fSMatthias Ringwald uint8_t direct_address_typ, bd_addr_t direct_address, uint8_t channel_map, uint8_t filter_policy){ 38077ba3d3fSMatthias Ringwald 38177ba3d3fSMatthias Ringwald // assert adv_int_min/max >= 2 * ADVERTISING_INTERVAL_MIN 38277ba3d3fSMatthias Ringwald 38377ba3d3fSMatthias Ringwald gap_adv_int_min = btstack_max(adv_int_min, 2 * ADVERTISING_INTERVAL_CONNECTABLE_MIN); 38477ba3d3fSMatthias Ringwald gap_adv_int_max = btstack_max(adv_int_max, 2 * ADVERTISING_INTERVAL_CONNECTABLE_MIN); 38577ba3d3fSMatthias Ringwald gap_adv_int_ms = gap_adv_int_min * 625 / 1000; 38677ba3d3fSMatthias Ringwald gap_adv_type = adv_type; 38777ba3d3fSMatthias Ringwald gap_direct_address_typ = direct_address_typ; 38877ba3d3fSMatthias Ringwald memcpy(gap_direct_address, &direct_address, 6); 38977ba3d3fSMatthias Ringwald gap_channel_map = channel_map; 39077ba3d3fSMatthias Ringwald gap_filter_policy = filter_policy; 39177ba3d3fSMatthias Ringwald 39277ba3d3fSMatthias Ringwald log_info("GAP Adv interval %u ms", gap_adv_int_ms); 39377ba3d3fSMatthias Ringwald } 394