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
lib_aci_is_pipe_available(aci_state_t * aci_stat,uint8_t pipe)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
lib_aci_is_pipe_closed(aci_state_t * aci_stat,uint8_t pipe)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
lib_aci_is_discovery_finished(aci_state_t * aci_stat)96 bool lib_aci_is_discovery_finished(aci_state_t *aci_stat)
97 {
98 return(aci_stat->pipes_open_bitmap[0]&0x01);
99 }
100
lib_aci_board_init(aci_state_t * aci_stat)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
lib_aci_init(aci_state_t * aci_stat,bool debug)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
lib_aci_get_nb_available_credits(aci_state_t * aci_stat)205 uint8_t lib_aci_get_nb_available_credits(aci_state_t *aci_stat)
206 {
207 return aci_stat->data_credit_available;
208 }
209
lib_aci_get_cx_interval_ms(aci_state_t * aci_stat)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
lib_aci_get_cx_interval(aci_state_t * aci_stat)223 uint16_t lib_aci_get_cx_interval(aci_state_t *aci_stat)
224 {
225 return aci_stat->connection_interval;
226 }
227
228
lib_aci_get_slave_latency(aci_state_t * aci_stat)229 uint16_t lib_aci_get_slave_latency(aci_state_t *aci_stat)
230 {
231 return aci_stat->slave_latency;
232 }
233
234
lib_aci_set_app_latency(uint16_t latency,aci_app_latency_mode_t latency_mode)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
lib_aci_test(aci_test_mode_change_t enter_exit_test_mode)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
lib_aci_sleep()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
lib_aci_radio_reset()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
lib_aci_direct_connect()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
lib_aci_device_version()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
lib_aci_set_local_data(aci_state_t * aci_stat,uint8_t pipe,uint8_t * p_value,uint8_t size)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
lib_aci_connect(uint16_t run_timeout,uint16_t adv_interval)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
lib_aci_disconnect(aci_state_t * aci_stat,aci_disconnect_reason_t reason)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
lib_aci_bond(uint16_t run_timeout,uint16_t adv_interval)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
lib_aci_wakeup()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
lib_aci_set_tx_power(aci_device_output_power_t tx_power)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
lib_aci_get_address()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
lib_aci_get_temperature()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
lib_aci_get_battery_level()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
lib_aci_send_data(uint8_t pipe,uint8_t * p_value,uint8_t size)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
lib_aci_request_data(aci_state_t * aci_stat,uint8_t pipe)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
lib_aci_change_timing(uint16_t minimun_cx_interval,uint16_t maximum_cx_interval,uint16_t slave_latency,uint16_t timeout)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
lib_aci_change_timing_GAP_PPCP()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
lib_aci_open_remote_pipe(aci_state_t * aci_stat,uint8_t pipe)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
lib_aci_close_remote_pipe(aci_state_t * aci_stat,uint8_t pipe)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
lib_aci_set_key(aci_key_type_t key_rsp_type,uint8_t * key,uint8_t len)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
lib_aci_echo_msg(uint8_t msg_size,uint8_t * p_msg_data)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
lib_aci_bond_request()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
lib_aci_event_peek(hal_aci_evt_t * p_aci_evt_data)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
lib_aci_event_get(aci_state_t * aci_stat,hal_aci_evt_t * p_aci_evt_data)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
lib_aci_send_ack(aci_state_t * aci_stat,const uint8_t pipe)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
lib_aci_send_nack(aci_state_t * aci_stat,const uint8_t pipe,const uint8_t error_code)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
lib_aci_broadcast(const uint16_t timeout,const uint16_t adv_interval)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
lib_aci_open_adv_pipes(const uint8_t * const adv_service_data_pipes)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
lib_aci_open_adv_pipe(const uint8_t pipe)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
lib_aci_read_dynamic_data()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
lib_aci_write_dynamic_data(uint8_t sequence_number,uint8_t * dynamic_data,uint8_t length)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
lib_aci_dtm_command(uint8_t dtm_command_msbyte,uint8_t dtm_command_lsbyte)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
lib_aci_flush(void)708 void lib_aci_flush(void)
709 {
710 hal_aci_tl_q_flush();
711 }
712
lib_aci_debug_print(bool enable)713 void lib_aci_debug_print(bool enable)
714 {
715 hal_aci_tl_debug_print(enable);
716
717 }
718
lib_aci_pin_reset(void)719 void lib_aci_pin_reset(void)
720 {
721 hal_aci_tl_pin_reset();
722 }
723
lib_aci_event_queue_empty(void)724 bool lib_aci_event_queue_empty(void)
725 {
726 return hal_aci_tl_rx_q_empty();
727 }
728
lib_aci_event_queue_full(void)729 bool lib_aci_event_queue_full(void)
730 {
731 return hal_aci_tl_rx_q_full();
732 }
733
lib_aci_command_queue_empty(void)734 bool lib_aci_command_queue_empty(void)
735 {
736 return hal_aci_tl_tx_q_empty();
737 }
738
lib_aci_command_queue_full(void)739 bool lib_aci_command_queue_full(void)
740 {
741 return hal_aci_tl_tx_q_full();
742 }
743