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