/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef H_BLE_LL_SCHED_ #define H_BLE_LL_SCHED_ #ifdef __cplusplus extern "C" { #endif /* Time per BLE scheduler slot */ #define BLE_LL_SCHED_USECS_PER_SLOT (1250) /* * Worst case time needed for scheduled advertising item. This is the longest * possible time to receive a scan request and send a scan response (with the * appropriate IFS time between them). This number is calculated using the * following formula: IFS + SCAN_REQ + IFS + SCAN_RSP = 150 + 176 + 150 + 376. * Note: worst case time to tx adv, rx scan req and send scan rsp is 1228 usecs. * This assumes maximum sized advertising PDU and scan response PDU. * * For connectable advertising events no scan request is allowed. In this case * we just need to receive a connect request PDU: IFS + CONNECT_REQ = 150 + 352. * Note: worst-case is 376 + 150 + 352 = 878 usecs * * NOTE: The advertising PDU transmit time is NOT included here since we know * how long that will take (worst-case is 376 usecs). */ #define BLE_LL_SCHED_ADV_MAX_USECS (852) #define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS (502) #define BLE_LL_SCHED_MAX_ADV_PDU_USECS (376) /* * This is the offset from the start of the scheduled item until the actual * tx/rx should occur, in ticks. */ extern uint8_t g_ble_ll_sched_offset_ticks; /* * This is the number of slots needed to transmit and receive a maximum * size PDU, including an IFS time before each. The actual time is * 2120 usecs for tx/rx and 150 for IFS = 4540 usecs. */ #define BLE_LL_SCHED_MAX_TXRX_SLOT (4 * BLE_LL_SCHED_USECS_PER_SLOT) /* BLE scheduler errors */ #define BLE_LL_SCHED_ERR_OVERLAP (1) /* Types of scheduler events */ #define BLE_LL_SCHED_TYPE_ADV (1) #define BLE_LL_SCHED_TYPE_SCAN (2) #define BLE_LL_SCHED_TYPE_CONN (3) #define BLE_LL_SCHED_TYPE_DTM (5) #define BLE_LL_SCHED_TYPE_PERIODIC (6) #define BLE_LL_SCHED_TYPE_SYNC (7) #define BLE_LL_SCHED_TYPE_SCAN_AUX (8) /* Return values for schedule callback. */ #define BLE_LL_SCHED_STATE_RUNNING (0) #define BLE_LL_SCHED_STATE_DONE (1) /* Callback function */ struct ble_ll_sched_item; typedef int (*sched_cb_func)(struct ble_ll_sched_item *sch); typedef void (*sched_remove_cb_func)(struct ble_ll_sched_item *sch); /* * Schedule item * sched_type: This is the type of the schedule item. * enqueued: Flag denoting if item is on the scheduler list. 0: no, 1:yes * remainder: # of usecs from offset till tx/rx should occur * txrx_offset: Number of ticks from start time until tx/rx should occur. * */ struct ble_ll_sched_item { uint8_t sched_type; uint8_t enqueued; uint8_t remainder; uint32_t start_time; uint32_t end_time; void *cb_arg; sched_cb_func sched_cb; TAILQ_ENTRY(ble_ll_sched_item) link; }; /* Initialize the scheduler */ int ble_ll_sched_init(void); /* Remove item(s) from schedule */ int ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch); void ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb); /* Schedule a new master connection */ struct ble_ll_conn_sm; int ble_ll_sched_conn_central_new(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len); /* Schedule a new slave connection */ int ble_ll_sched_conn_periph_new(struct ble_ll_conn_sm *connsm); struct ble_ll_adv_sm; typedef void ble_ll_sched_adv_new_cb(struct ble_ll_adv_sm *advsm, uint32_t sch_start, void *arg); /* Schedule a new advertising event */ int ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb, void *arg); /* Schedule periodic advertising event */ int ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, bool first_event); int ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, uint32_t anchor_point, uint8_t anchor_point_usecs, uint32_t window_widening, int8_t phy_mode); int ble_ll_sched_sync(struct ble_ll_sched_item *sch, uint32_t beg_cputime, uint32_t rem_usecs, uint32_t offset, int8_t phy_mode); /* Reschedule an advertising event */ int ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t max_delay_ticks); /* Reschedule and advertising pdu */ int ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch); /* Reschedule a connection that had previously been scheduled or that is over */ int ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm * connsm); /** * Called to determine when the next scheduled event will occur. * * If there are not scheduled events this function returns 0; otherwise it * returns 1 and *next_event_time is set to the start time of the next event. * * @param next_event_time cputime at which next scheduled event will occur * * @return int 0: No events are scheduled 1: there is an upcoming event */ int ble_ll_sched_next_time(uint32_t *next_event_time); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) struct ble_ll_scan_sm; struct ble_ll_aux_data; int ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, struct ble_ll_scan_sm *scansm, struct ble_ll_aux_data *aux_scan); int ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time, uint8_t pdu_time_rem, uint32_t offset_us); #endif /* Stop the scheduler */ void ble_ll_sched_stop(void); #if MYNEWT_VAL(BLE_LL_DTM) int ble_ll_sched_dtm(struct ble_ll_sched_item *sch); #endif #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) #if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED) void ble_ll_sched_css_set_params(uint32_t slot_us, uint32_t period_slots); #endif void ble_ll_sched_css_set_conn_anchor(struct ble_ll_conn_sm *connsm); #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED) static inline uint32_t ble_ll_sched_css_get_slot_us(void) { return MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_SLOT_US); } static inline uint32_t ble_ll_sched_css_get_period_slots(void) { return MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_PERIOD_SLOTS); } static inline uint32_t ble_ll_sched_css_get_conn_interval_us(void) { return ble_ll_sched_css_get_period_slots() * ble_ll_sched_css_get_slot_us() / 1250; } #else uint32_t ble_ll_sched_css_get_slot_us(void); uint32_t ble_ll_sched_css_get_period_slots(void); uint32_t ble_ll_sched_css_get_conn_interval_us(void); #endif #endif #ifdef __cplusplus } #endif #endif /* H_LL_SCHED_ */