1 /* Copyright (c) 2014, Nordic Semiconductor ASA 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to deal 5 * in the Software without restriction, including without limitation the rights 6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 * copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in all 11 * copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 * SOFTWARE. 20 */ 21 22 /** @file 23 @brief Implementation of the ACI library. 24 */ 25 26 #include "hal_platform.h" 27 #include "aci.h" 28 #include "aci_cmds.h" 29 #include "aci_evts.h" 30 #include "aci_protocol_defines.h" 31 #include "acilib_defs.h" 32 #include "acilib_if.h" 33 #include "hal_aci_tl.h" 34 #include "aci_queue.h" 35 #include "lib_aci.h" 36 37 38 #define LIB_ACI_DEFAULT_CREDIT_NUMBER 1 39 40 /* 41 Global additionally used used in aci_setup 42 */ 43 hal_aci_data_t msg_to_send; 44 45 46 static services_pipe_type_mapping_t * p_services_pipe_type_map; 47 static hal_aci_data_t * p_setup_msgs; 48 49 50 51 52 static bool is_request_operation_pending; 53 static bool is_indicate_operation_pending; 54 static bool is_open_remote_pipe_pending; 55 static bool is_close_remote_pipe_pending; 56 57 static uint8_t request_operation_pipe = 0; 58 static uint8_t indicate_operation_pipe = 0; 59 60 61 // The following structure (aci_cmd_params_open_adv_pipe) will be used to store the complete command 62 // including the pipes to be opened. 63 static aci_cmd_params_open_adv_pipe_t aci_cmd_params_open_adv_pipe; 64 65 66 67 extern aci_queue_t aci_rx_q; 68 extern aci_queue_t aci_tx_q; 69 70 bool lib_aci_is_pipe_available(aci_state_t *aci_stat, uint8_t pipe) 71 { 72 uint8_t byte_idx; 73 74 byte_idx = pipe / 8; 75 if (aci_stat->pipes_open_bitmap[byte_idx] & (0x01 << (pipe % 8))) 76 { 77 return(true); 78 } 79 return(false); 80 } 81 82 83 bool lib_aci_is_pipe_closed(aci_state_t *aci_stat, uint8_t pipe) 84 { 85 uint8_t byte_idx; 86 87 byte_idx = pipe / 8; 88 if (aci_stat->pipes_closed_bitmap[byte_idx] & (0x01 << (pipe % 8))) 89 { 90 return(true); 91 } 92 return(false); 93 } 94 95 96 bool lib_aci_is_discovery_finished(aci_state_t *aci_stat) 97 { 98 return(aci_stat->pipes_open_bitmap[0]&0x01); 99 } 100 101 void lib_aci_board_init(aci_state_t *aci_stat) 102 { 103 hal_aci_evt_t *aci_data = NULL; 104 aci_data = (hal_aci_evt_t *)&msg_to_send; 105 106 if (REDBEARLAB_SHIELD_V1_1 == aci_stat->aci_pins.board_name) 107 { 108 /* 109 The Bluetooth low energy Arduino shield v1.1 requires about 100ms to reset. 110 This is not required for the nRF2740, nRF2741 modules 111 */ 112 usleep(100000); 113 114 /* 115 Send the soft reset command to the nRF8001 to get the nRF8001 to a known state. 116 */ 117 lib_aci_radio_reset(); 118 119 while (1) 120 { 121 /*Wait for the command response of the radio reset command. 122 as the nRF8001 will be in either SETUP or STANDBY after the ACI Reset Radio is processed 123 */ 124 125 126 if (true == lib_aci_event_get(aci_stat, aci_data)) 127 { 128 aci_evt_t * aci_evt; 129 aci_evt = &(aci_data->evt); 130 131 if (ACI_EVT_CMD_RSP == aci_evt->evt_opcode) 132 { 133 if (ACI_STATUS_ERROR_DEVICE_STATE_INVALID == aci_evt->params.cmd_rsp.cmd_status) //in SETUP 134 { 135 //Inject a Device Started Event Setup to the ACI Event Queue 136 msg_to_send.buffer[0] = 4; //Length 137 msg_to_send.buffer[1] = 0x81; //Device Started Event 138 msg_to_send.buffer[2] = 0x02; //Setup 139 msg_to_send.buffer[3] = 0; //Hardware Error -> None 140 msg_to_send.buffer[4] = 2; //Data Credit Available 141 aci_queue_enqueue(&aci_rx_q, &msg_to_send); 142 } 143 else if (ACI_STATUS_SUCCESS == aci_evt->params.cmd_rsp.cmd_status) //We are now in STANDBY 144 { 145 //Inject a Device Started Event Standby to the ACI Event Queue 146 msg_to_send.buffer[0] = 4; //Length 147 msg_to_send.buffer[1] = 0x81; //Device Started Event 148 msg_to_send.buffer[2] = 0x03; //Standby 149 msg_to_send.buffer[3] = 0; //Hardware Error -> None 150 msg_to_send.buffer[4] = 2; //Data Credit Available 151 aci_queue_enqueue(&aci_rx_q, &msg_to_send); 152 } 153 else if (ACI_STATUS_ERROR_CMD_UNKNOWN == aci_evt->params.cmd_rsp.cmd_status) //We are now in TEST 154 { 155 //Inject a Device Started Event Test to the ACI Event Queue 156 msg_to_send.buffer[0] = 4; //Length 157 msg_to_send.buffer[1] = 0x81; //Device Started Event 158 msg_to_send.buffer[2] = 0x01; //Test 159 msg_to_send.buffer[3] = 0; //Hardware Error -> None 160 msg_to_send.buffer[4] = 0; //Data Credit Available 161 aci_queue_enqueue(&aci_rx_q, &msg_to_send); 162 } 163 164 printf ("BREAK\n"); 165 //Break out of the while loop 166 break; 167 } 168 else 169 { 170 //Serial.println(F("Discard any other ACI Events")); 171 } 172 173 } 174 } 175 } 176 } 177 178 179 void lib_aci_init(aci_state_t *aci_stat, bool debug) 180 { 181 uint8_t i; 182 183 for (i = 0; i < PIPES_ARRAY_SIZE; i++) { 184 aci_stat->pipes_open_bitmap[i] = 0; 185 aci_stat->pipes_closed_bitmap[i] = 0; 186 aci_cmd_params_open_adv_pipe.pipes[i] = 0; 187 } 188 189 is_request_operation_pending = false; 190 is_indicate_operation_pending = false; 191 is_open_remote_pipe_pending = false; 192 is_close_remote_pipe_pending = false; 193 194 request_operation_pipe = 0; 195 indicate_operation_pipe = 0; 196 197 p_services_pipe_type_map = aci_stat->aci_setup_info.services_pipe_type_mapping; 198 p_setup_msgs = aci_stat->aci_setup_info.setup_msgs; 199 200 hal_aci_tl_init (&aci_stat->aci_pins, debug); 201 lib_aci_board_init (aci_stat); 202 } 203 204 205 uint8_t lib_aci_get_nb_available_credits(aci_state_t *aci_stat) 206 { 207 return aci_stat->data_credit_available; 208 } 209 210 uint16_t lib_aci_get_cx_interval_ms(aci_state_t *aci_stat) 211 { 212 uint32_t cx_rf_interval_ms_32bits; 213 uint16_t cx_rf_interval_ms; 214 215 cx_rf_interval_ms_32bits = aci_stat->connection_interval; 216 cx_rf_interval_ms_32bits *= 125; // the connection interval is given in multiples of 0.125 milliseconds 217 cx_rf_interval_ms = cx_rf_interval_ms_32bits / 100; 218 219 return cx_rf_interval_ms; 220 } 221 222 223 uint16_t lib_aci_get_cx_interval(aci_state_t *aci_stat) 224 { 225 return aci_stat->connection_interval; 226 } 227 228 229 uint16_t lib_aci_get_slave_latency(aci_state_t *aci_stat) 230 { 231 return aci_stat->slave_latency; 232 } 233 234 235 bool lib_aci_set_app_latency(uint16_t latency, aci_app_latency_mode_t latency_mode) 236 { 237 aci_cmd_params_set_app_latency_t aci_set_app_latency; 238 239 aci_set_app_latency.mode = latency_mode; 240 aci_set_app_latency.latency = latency; 241 acil_encode_cmd_set_app_latency(&(msg_to_send.buffer[0]), &aci_set_app_latency); 242 243 return hal_aci_tl_send(&msg_to_send); 244 } 245 246 247 bool lib_aci_test(aci_test_mode_change_t enter_exit_test_mode) 248 { 249 aci_cmd_params_test_t aci_cmd_params_test; 250 aci_cmd_params_test.test_mode_change = enter_exit_test_mode; 251 acil_encode_cmd_set_test_mode(&(msg_to_send.buffer[0]), &aci_cmd_params_test); 252 return hal_aci_tl_send(&msg_to_send); 253 } 254 255 256 bool lib_aci_sleep() 257 { 258 acil_encode_cmd_sleep(&(msg_to_send.buffer[0])); 259 return hal_aci_tl_send(&msg_to_send); 260 } 261 262 263 bool lib_aci_radio_reset() 264 { 265 acil_encode_baseband_reset(&(msg_to_send.buffer[0])); 266 return hal_aci_tl_send(&msg_to_send); 267 } 268 269 270 bool lib_aci_direct_connect() 271 { 272 acil_encode_direct_connect(&(msg_to_send.buffer[0])); 273 return hal_aci_tl_send(&msg_to_send); 274 } 275 276 277 bool lib_aci_device_version() 278 { 279 acil_encode_cmd_get_device_version(&(msg_to_send.buffer[0])); 280 return hal_aci_tl_send(&msg_to_send); 281 } 282 283 284 bool lib_aci_set_local_data(aci_state_t *aci_stat, uint8_t pipe, uint8_t *p_value, uint8_t size) 285 { 286 aci_cmd_params_set_local_data_t aci_cmd_params_set_local_data; 287 288 if ((p_services_pipe_type_map[pipe-1].location != ACI_STORE_LOCAL) 289 || 290 (size > ACI_PIPE_TX_DATA_MAX_LEN)) 291 { 292 return false; 293 } 294 295 aci_cmd_params_set_local_data.tx_data.pipe_number = pipe; 296 memcpy(&(aci_cmd_params_set_local_data.tx_data.aci_data[0]), p_value, size); 297 acil_encode_cmd_set_local_data(&(msg_to_send.buffer[0]), &aci_cmd_params_set_local_data, size); 298 return hal_aci_tl_send(&msg_to_send); 299 } 300 301 bool lib_aci_connect(uint16_t run_timeout, uint16_t adv_interval) 302 { 303 aci_cmd_params_connect_t aci_cmd_params_connect; 304 aci_cmd_params_connect.timeout = run_timeout; 305 aci_cmd_params_connect.adv_interval = adv_interval; 306 acil_encode_cmd_connect(&(msg_to_send.buffer[0]), &aci_cmd_params_connect); 307 return hal_aci_tl_send(&msg_to_send); 308 } 309 310 311 bool lib_aci_disconnect(aci_state_t *aci_stat, aci_disconnect_reason_t reason) 312 { 313 bool ret_val; 314 uint8_t i; 315 aci_cmd_params_disconnect_t aci_cmd_params_disconnect; 316 aci_cmd_params_disconnect.reason = reason; 317 acil_encode_cmd_disconnect(&(msg_to_send.buffer[0]), &aci_cmd_params_disconnect); 318 ret_val = hal_aci_tl_send(&msg_to_send); 319 // If we have actually sent the disconnect 320 if (ret_val) 321 { 322 // Update pipes immediately so that while the disconnect is happening, 323 // the application can't attempt sending another message 324 // If the application sends another message before we updated this 325 // a ACI Pipe Error Event will be received from nRF8001 326 for (i=0; i < PIPES_ARRAY_SIZE; i++) 327 { 328 aci_stat->pipes_open_bitmap[i] = 0; 329 aci_stat->pipes_closed_bitmap[i] = 0; 330 } 331 } 332 return ret_val; 333 } 334 335 336 bool lib_aci_bond(uint16_t run_timeout, uint16_t adv_interval) 337 { 338 aci_cmd_params_bond_t aci_cmd_params_bond; 339 aci_cmd_params_bond.timeout = run_timeout; 340 aci_cmd_params_bond.adv_interval = adv_interval; 341 acil_encode_cmd_bond(&(msg_to_send.buffer[0]), &aci_cmd_params_bond); 342 return hal_aci_tl_send(&msg_to_send); 343 } 344 345 346 bool lib_aci_wakeup() 347 { 348 acil_encode_cmd_wakeup(&(msg_to_send.buffer[0])); 349 return hal_aci_tl_send(&msg_to_send); 350 } 351 352 353 bool lib_aci_set_tx_power(aci_device_output_power_t tx_power) 354 { 355 aci_cmd_params_set_tx_power_t aci_cmd_params_set_tx_power; 356 aci_cmd_params_set_tx_power.device_power = tx_power; 357 acil_encode_cmd_set_radio_tx_power(&(msg_to_send.buffer[0]), &aci_cmd_params_set_tx_power); 358 return hal_aci_tl_send(&msg_to_send); 359 } 360 361 362 bool lib_aci_get_address() 363 { 364 acil_encode_cmd_get_address(&(msg_to_send.buffer[0])); 365 return hal_aci_tl_send(&msg_to_send); 366 } 367 368 369 bool lib_aci_get_temperature() 370 { 371 acil_encode_cmd_temparature(&(msg_to_send.buffer[0])); 372 return hal_aci_tl_send(&msg_to_send); 373 } 374 375 376 bool lib_aci_get_battery_level() 377 { 378 acil_encode_cmd_battery_level(&(msg_to_send.buffer[0])); 379 return hal_aci_tl_send(&msg_to_send); 380 } 381 382 383 bool lib_aci_send_data(uint8_t pipe, uint8_t *p_value, uint8_t size) 384 { 385 bool ret_val = false; 386 aci_cmd_params_send_data_t aci_cmd_params_send_data; 387 388 389 if(!((p_services_pipe_type_map[pipe-1].pipe_type == ACI_TX) || 390 (p_services_pipe_type_map[pipe-1].pipe_type == ACI_TX_ACK))) 391 { 392 return false; 393 } 394 395 if (size > ACI_PIPE_TX_DATA_MAX_LEN) 396 { 397 return false; 398 } 399 { 400 aci_cmd_params_send_data.tx_data.pipe_number = pipe; 401 memcpy(&(aci_cmd_params_send_data.tx_data.aci_data[0]), p_value, size); 402 acil_encode_cmd_send_data(&(msg_to_send.buffer[0]), &aci_cmd_params_send_data, size); 403 404 ret_val = hal_aci_tl_send(&msg_to_send); 405 } 406 return ret_val; 407 } 408 409 410 bool lib_aci_request_data(aci_state_t *aci_stat, uint8_t pipe) 411 { 412 bool ret_val = false; 413 aci_cmd_params_request_data_t aci_cmd_params_request_data; 414 415 if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&&(p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_REQ))) 416 { 417 return false; 418 } 419 420 421 { 422 423 { 424 425 426 427 aci_cmd_params_request_data.pipe_number = pipe; 428 acil_encode_cmd_request_data(&(msg_to_send.buffer[0]), &aci_cmd_params_request_data); 429 430 ret_val = hal_aci_tl_send(&msg_to_send); 431 } 432 } 433 return ret_val; 434 } 435 436 437 bool lib_aci_change_timing(uint16_t minimun_cx_interval, uint16_t maximum_cx_interval, uint16_t slave_latency, uint16_t timeout) 438 { 439 aci_cmd_params_change_timing_t aci_cmd_params_change_timing; 440 aci_cmd_params_change_timing.conn_params.min_conn_interval = minimun_cx_interval; 441 aci_cmd_params_change_timing.conn_params.max_conn_interval = maximum_cx_interval; 442 aci_cmd_params_change_timing.conn_params.slave_latency = slave_latency; 443 aci_cmd_params_change_timing.conn_params.timeout_mult = timeout; 444 acil_encode_cmd_change_timing_req(&(msg_to_send.buffer[0]), &aci_cmd_params_change_timing); 445 return hal_aci_tl_send(&msg_to_send); 446 } 447 448 449 bool lib_aci_change_timing_GAP_PPCP() 450 { 451 acil_encode_cmd_change_timing_req_GAP_PPCP(&(msg_to_send.buffer[0])); 452 return hal_aci_tl_send(&msg_to_send); 453 } 454 455 456 bool lib_aci_open_remote_pipe(aci_state_t *aci_stat, uint8_t pipe) 457 { 458 bool ret_val = false; 459 aci_cmd_params_open_remote_pipe_t aci_cmd_params_open_remote_pipe; 460 461 if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&& 462 ((p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX)|| 463 (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK_AUTO)|| 464 (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK)))) 465 { 466 return false; 467 } 468 469 470 { 471 472 is_request_operation_pending = true; 473 is_open_remote_pipe_pending = true; 474 request_operation_pipe = pipe; 475 aci_cmd_params_open_remote_pipe.pipe_number = pipe; 476 acil_encode_cmd_open_remote_pipe(&(msg_to_send.buffer[0]), &aci_cmd_params_open_remote_pipe); 477 ret_val = hal_aci_tl_send(&msg_to_send); 478 } 479 return ret_val; 480 } 481 482 483 bool lib_aci_close_remote_pipe(aci_state_t *aci_stat, uint8_t pipe) 484 { 485 bool ret_val = false; 486 aci_cmd_params_close_remote_pipe_t aci_cmd_params_close_remote_pipe; 487 488 if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&& 489 ((p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX)|| 490 (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK_AUTO)|| 491 (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK)))) 492 { 493 return false; 494 } 495 496 497 { 498 499 is_request_operation_pending = true; 500 is_close_remote_pipe_pending = true; 501 request_operation_pipe = pipe; 502 aci_cmd_params_close_remote_pipe.pipe_number = pipe; 503 acil_encode_cmd_close_remote_pipe(&(msg_to_send.buffer[0]), &aci_cmd_params_close_remote_pipe); 504 ret_val = hal_aci_tl_send(&msg_to_send); 505 } 506 return ret_val; 507 } 508 509 510 bool lib_aci_set_key(aci_key_type_t key_rsp_type, uint8_t *key, uint8_t len) 511 { 512 aci_cmd_params_set_key_t aci_cmd_params_set_key; 513 aci_cmd_params_set_key.key_type = key_rsp_type; 514 memcpy((uint8_t*)&(aci_cmd_params_set_key.key), key, len); 515 acil_encode_cmd_set_key(&(msg_to_send.buffer[0]), &aci_cmd_params_set_key); 516 return hal_aci_tl_send(&msg_to_send); 517 } 518 519 520 bool lib_aci_echo_msg(uint8_t msg_size, uint8_t *p_msg_data) 521 { 522 aci_cmd_params_echo_t aci_cmd_params_echo; 523 if(msg_size > (ACI_ECHO_DATA_MAX_LEN)) 524 { 525 return false; 526 } 527 528 if (msg_size > (ACI_ECHO_DATA_MAX_LEN)) 529 { 530 msg_size = ACI_ECHO_DATA_MAX_LEN; 531 } 532 533 memcpy(&(aci_cmd_params_echo.echo_data[0]), p_msg_data, msg_size); 534 acil_encode_cmd_echo_msg(&(msg_to_send.buffer[0]), &aci_cmd_params_echo, msg_size); 535 536 return hal_aci_tl_send(&msg_to_send); 537 } 538 539 540 bool lib_aci_bond_request() 541 { 542 acil_encode_cmd_bond_security_request(&(msg_to_send.buffer[0])); 543 return hal_aci_tl_send(&msg_to_send); 544 } 545 546 bool lib_aci_event_peek(hal_aci_evt_t *p_aci_evt_data) 547 { 548 return hal_aci_tl_event_peek((hal_aci_data_t *)p_aci_evt_data); 549 } 550 551 bool lib_aci_event_get(aci_state_t *aci_stat, hal_aci_evt_t *p_aci_evt_data) 552 { 553 bool status = false; 554 555 status = hal_aci_tl_event_get((hal_aci_data_t *)p_aci_evt_data); 556 557 /** 558 Update the state of the ACI with the 559 ACI Events -> Pipe Status, Disconnected, Connected, Bond Status, Pipe Error 560 */ 561 if (true == status) 562 { 563 aci_evt_t * aci_evt; 564 565 aci_evt = &p_aci_evt_data->evt; 566 567 switch(aci_evt->evt_opcode) 568 { 569 case ACI_EVT_PIPE_STATUS: 570 { 571 uint8_t i=0; 572 573 for (i=0; i < PIPES_ARRAY_SIZE; i++) 574 { 575 aci_stat->pipes_open_bitmap[i] = aci_evt->params.pipe_status.pipes_open_bitmap[i]; 576 aci_stat->pipes_closed_bitmap[i] = aci_evt->params.pipe_status.pipes_closed_bitmap[i]; 577 } 578 } 579 break; 580 581 case ACI_EVT_DISCONNECTED: 582 { 583 uint8_t i=0; 584 585 for (i=0; i < PIPES_ARRAY_SIZE; i++) 586 { 587 aci_stat->pipes_open_bitmap[i] = 0; 588 aci_stat->pipes_closed_bitmap[i] = 0; 589 } 590 aci_stat->confirmation_pending = false; 591 aci_stat->data_credit_available = aci_stat->data_credit_total; 592 593 } 594 break; 595 596 case ACI_EVT_TIMING: 597 aci_stat->connection_interval = aci_evt->params.timing.conn_rf_interval; 598 aci_stat->slave_latency = aci_evt->params.timing.conn_slave_rf_latency; 599 aci_stat->supervision_timeout = aci_evt->params.timing.conn_rf_timeout; 600 break; 601 602 default: 603 /* Need default case to avoid compiler warnings about missing enum 604 * values on some platforms. 605 */ 606 break; 607 608 609 610 } 611 } 612 return status; 613 } 614 615 616 bool lib_aci_send_ack(aci_state_t *aci_stat, const uint8_t pipe) 617 { 618 bool ret_val = false; 619 { 620 acil_encode_cmd_send_data_ack(&(msg_to_send.buffer[0]), pipe); 621 622 ret_val = hal_aci_tl_send(&msg_to_send); 623 } 624 return ret_val; 625 } 626 627 628 bool lib_aci_send_nack(aci_state_t *aci_stat, const uint8_t pipe, const uint8_t error_code) 629 { 630 bool ret_val = false; 631 632 { 633 634 acil_encode_cmd_send_data_nack(&(msg_to_send.buffer[0]), pipe, error_code); 635 ret_val = hal_aci_tl_send(&msg_to_send); 636 } 637 return ret_val; 638 } 639 640 641 bool lib_aci_broadcast(const uint16_t timeout, const uint16_t adv_interval) 642 { 643 aci_cmd_params_broadcast_t aci_cmd_params_broadcast; 644 if (timeout > 16383) 645 { 646 return false; 647 } 648 649 // The adv_interval should be between 160 and 16384 (which translates to the advertisement 650 // interval values 100 ms and 10.24 s. 651 if ((160 > adv_interval) || (adv_interval > 16384)) 652 { 653 return false; 654 } 655 656 aci_cmd_params_broadcast.timeout = timeout; 657 aci_cmd_params_broadcast.adv_interval = adv_interval; 658 acil_encode_cmd_broadcast(&(msg_to_send.buffer[0]), &aci_cmd_params_broadcast); 659 return hal_aci_tl_send(&msg_to_send); 660 } 661 662 663 bool lib_aci_open_adv_pipes(const uint8_t * const adv_service_data_pipes) 664 { 665 uint8_t i; 666 667 for (i = 0; i < PIPES_ARRAY_SIZE; i++) 668 { 669 aci_cmd_params_open_adv_pipe.pipes[i] = adv_service_data_pipes[i]; 670 } 671 672 acil_encode_cmd_open_adv_pipes(&(msg_to_send.buffer[0]), &aci_cmd_params_open_adv_pipe); 673 return hal_aci_tl_send(&msg_to_send); 674 } 675 676 bool lib_aci_open_adv_pipe(const uint8_t pipe) 677 { 678 uint8_t byte_idx = pipe / 8; 679 680 aci_cmd_params_open_adv_pipe.pipes[byte_idx] |= (0x01 << (pipe % 8)); 681 acil_encode_cmd_open_adv_pipes(&(msg_to_send.buffer[0]), &aci_cmd_params_open_adv_pipe); 682 return hal_aci_tl_send(&msg_to_send); 683 } 684 685 686 bool lib_aci_read_dynamic_data() 687 { 688 acil_encode_cmd_read_dynamic_data(&(msg_to_send.buffer[0])); 689 return hal_aci_tl_send(&msg_to_send); 690 } 691 692 693 bool lib_aci_write_dynamic_data(uint8_t sequence_number, uint8_t* dynamic_data, uint8_t length) 694 { 695 acil_encode_cmd_write_dynamic_data(&(msg_to_send.buffer[0]), sequence_number, dynamic_data, length); 696 return hal_aci_tl_send(&msg_to_send); 697 } 698 699 bool lib_aci_dtm_command(uint8_t dtm_command_msbyte, uint8_t dtm_command_lsbyte) 700 { 701 aci_cmd_params_dtm_cmd_t aci_cmd_params_dtm_cmd; 702 aci_cmd_params_dtm_cmd.cmd_msb = dtm_command_msbyte; 703 aci_cmd_params_dtm_cmd.cmd_lsb = dtm_command_lsbyte; 704 acil_encode_cmd_dtm_cmd(&(msg_to_send.buffer[0]), &aci_cmd_params_dtm_cmd); 705 return hal_aci_tl_send(&msg_to_send); 706 } 707 708 void lib_aci_flush(void) 709 { 710 hal_aci_tl_q_flush(); 711 } 712 713 void lib_aci_debug_print(bool enable) 714 { 715 hal_aci_tl_debug_print(enable); 716 717 } 718 719 void lib_aci_pin_reset(void) 720 { 721 hal_aci_tl_pin_reset(); 722 } 723 724 bool lib_aci_event_queue_empty(void) 725 { 726 return hal_aci_tl_rx_q_empty(); 727 } 728 729 bool lib_aci_event_queue_full(void) 730 { 731 return hal_aci_tl_rx_q_full(); 732 } 733 734 bool lib_aci_command_queue_empty(void) 735 { 736 return hal_aci_tl_tx_q_empty(); 737 } 738 739 bool lib_aci_command_queue_full(void) 740 { 741 return hal_aci_tl_tx_q_full(); 742 } 743