1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 #ifndef H_BLE_LL_SCHED_ 21 #define H_BLE_LL_SCHED_ 22 23 #ifdef __cplusplus 24 extern "C" { 25 #endif 26 27 /* Time per BLE scheduler slot */ 28 #define BLE_LL_SCHED_USECS_PER_SLOT (1250) 29 #define BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT (41) /* 1 tick = 30.517 usecs */ 30 31 /* 32 * Worst case time needed for scheduled advertising item. This is the longest 33 * possible time to receive a scan request and send a scan response (with the 34 * appropriate IFS time between them). This number is calculated using the 35 * following formula: IFS + SCAN_REQ + IFS + SCAN_RSP = 150 + 176 + 150 + 376. 36 * Note: worst case time to tx adv, rx scan req and send scan rsp is 1228 usecs. 37 * This assumes maximum sized advertising PDU and scan response PDU. 38 * 39 * For connectable advertising events no scan request is allowed. In this case 40 * we just need to receive a connect request PDU: IFS + CONNECT_REQ = 150 + 352. 41 * Note: worst-case is 376 + 150 + 352 = 878 usecs 42 * 43 * NOTE: The advertising PDU transmit time is NOT included here since we know 44 * how long that will take (worst-case is 376 usecs). 45 */ 46 #define BLE_LL_SCHED_ADV_MAX_USECS (852) 47 #define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS (502) 48 #define BLE_LL_SCHED_MAX_ADV_PDU_USECS (376) 49 50 /* We don't know how big aux packet will be. It depends on adv packet len which 51 * can be up to 256. For now we fix it to 128 bytes, but we can optimize it. 52 */ 53 #define BLE_LL_SCHED_AUX_PTR_DFLT_BYTES_NUM (128) 54 55 /* 56 * This is the offset from the start of the scheduled item until the actual 57 * tx/rx should occur, in ticks. 58 */ 59 extern uint8_t g_ble_ll_sched_offset_ticks; 60 61 /* 62 * This is the number of slots needed to transmit and receive a maximum 63 * size PDU, including an IFS time before each. The actual time is 64 * 2120 usecs for tx/rx and 150 for IFS = 4540 usecs. 65 */ 66 #define BLE_LL_SCHED_MAX_TXRX_SLOT (4 * BLE_LL_SCHED_USECS_PER_SLOT) 67 68 /* BLE scheduler errors */ 69 #define BLE_LL_SCHED_ERR_OVERLAP (1) 70 71 /* Types of scheduler events */ 72 #define BLE_LL_SCHED_TYPE_ADV (1) 73 #define BLE_LL_SCHED_TYPE_SCAN (2) 74 #define BLE_LL_SCHED_TYPE_CONN (3) 75 #define BLE_LL_SCHED_TYPE_AUX_SCAN (4) 76 #define BLE_LL_SCHED_TYPE_DTM (5) 77 78 /* Return values for schedule callback. */ 79 #define BLE_LL_SCHED_STATE_RUNNING (0) 80 #define BLE_LL_SCHED_STATE_DONE (1) 81 82 /* Callback function */ 83 struct ble_ll_sched_item; 84 typedef int (*sched_cb_func)(struct ble_ll_sched_item *sch); 85 typedef void (*sched_remove_cb_func)(struct ble_ll_sched_item *sch); 86 /* 87 * Strict connection scheduling (for the master) is different than how 88 * connections are normally scheduled. With strict connection scheduling we 89 * introduce the concept of a "period". A period is a collection of slots. Each 90 * slot is 1.25 msecs in length. The number of slots in a period is determined 91 * by the syscfg value BLE_LL_CONN_INIT_SLOTS. A collection of periods is called 92 * an epoch. The length of an epoch is determined by the number of connections 93 * (BLE_MAX_CONNECTIONS plus BLE_LL_ADD_STRICT_SCHED_PERIODS). Connections 94 * will be scheduled at period boundaries. Any scanning/initiating/advertising 95 * will be done in unused periods, if possible. 96 */ 97 #if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) 98 #define BLE_LL_SCHED_PERIODS (MYNEWT_VAL(BLE_MAX_CONNECTIONS) + \ 99 MYNEWT_VAL(BLE_LL_ADD_STRICT_SCHED_PERIODS)) 100 101 struct ble_ll_sched_obj 102 { 103 uint8_t sch_num_occ_periods; 104 uint32_t sch_occ_period_mask; 105 uint32_t sch_ticks_per_period; 106 uint32_t sch_ticks_per_epoch; 107 uint32_t sch_epoch_start; 108 }; 109 110 extern struct ble_ll_sched_obj g_ble_ll_sched_data; 111 112 /* 113 * XXX: TODO: 114 * -> How do we know epoch start is up to date? Not wrapped? 115 * -> for now, only do this with no more than 32 connections. 116 * -> Do not let initiating occur if no empty sched slots 117 */ 118 #endif 119 120 /* 121 * Schedule item 122 * sched_type: This is the type of the schedule item. 123 * enqueued: Flag denoting if item is on the scheduler list. 0: no, 1:yes 124 * remainder: # of usecs from offset till tx/rx should occur 125 * txrx_offset: Number of ticks from start time until tx/rx should occur. 126 * 127 */ 128 struct ble_ll_sched_item 129 { 130 uint8_t sched_type; 131 uint8_t enqueued; 132 uint8_t remainder; 133 uint32_t start_time; 134 uint32_t end_time; 135 void *cb_arg; 136 sched_cb_func sched_cb; 137 TAILQ_ENTRY(ble_ll_sched_item) link; 138 }; 139 140 /* Initialize the scheduler */ 141 int ble_ll_sched_init(void); 142 143 /* Remove item(s) from schedule */ 144 int ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch); 145 146 void ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb); 147 148 /* Schedule a new master connection */ 149 struct ble_ll_conn_sm; 150 int ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, 151 struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len); 152 153 /* Schedule a new slave connection */ 154 int ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm); 155 156 struct ble_ll_adv_sm; 157 typedef void ble_ll_sched_adv_new_cb(struct ble_ll_adv_sm *advsm, 158 uint32_t sch_start, void *arg); 159 160 /* Schedule a new advertising event */ 161 int ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, 162 ble_ll_sched_adv_new_cb cb, void *arg); 163 164 /* Reschedule an advertising event */ 165 int ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start, 166 uint32_t max_delay_ticks); 167 168 /* Reschedule and advertising pdu */ 169 int ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch); 170 171 /* Reschedule a connection that had previously been scheduled or that is over */ 172 int ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm * connsm); 173 174 /** 175 * Called to determine when the next scheduled event will occur. 176 * 177 * If there are not scheduled events this function returns 0; otherwise it 178 * returns 1 and *next_event_time is set to the start time of the next event. 179 * 180 * @param next_event_time cputime at which next scheduled event will occur 181 * 182 * @return int 0: No events are scheduled 1: there is an upcoming event 183 */ 184 int ble_ll_sched_next_time(uint32_t *next_event_time); 185 186 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) 187 struct ble_ll_scan_sm; 188 struct ble_ll_aux_data; 189 int ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, 190 struct ble_ll_scan_sm *scansm, 191 struct ble_ll_aux_data *aux_scan); 192 193 int ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode); 194 #endif 195 196 /* Stop the scheduler */ 197 void ble_ll_sched_stop(void); 198 199 #ifdef BLE_XCVR_RFCLK 200 /* Check if RF clock needs to be restarted */ 201 void ble_ll_sched_rfclk_chk_restart(void); 202 #endif 203 204 #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1 205 int ble_ll_sched_dtm(struct ble_ll_sched_item *sch); 206 #endif 207 208 #ifdef __cplusplus 209 } 210 #endif 211 212 #endif /* H_LL_SCHED_ */ 213