xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_hs_hci.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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 #include <stdint.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include "os/os.h"
24 #include "mem/mem.h"
25 #include "nimble/ble_hci_trans.h"
26 #include "host/ble_monitor.h"
27 #include "ble_hs_priv.h"
28 #include "ble_hs_dbg_priv.h"
29 #include "ble_monitor_priv.h"
30 
31 #define BLE_HCI_CMD_TIMEOUT_MS  2000
32 
33 static struct ble_npl_mutex ble_hs_hci_mutex;
34 static struct ble_npl_sem ble_hs_hci_sem;
35 
36 static uint8_t *ble_hs_hci_ack;
37 static uint16_t ble_hs_hci_buf_sz;
38 static uint8_t ble_hs_hci_max_pkts;
39 static uint32_t ble_hs_hci_sup_feat;
40 static uint8_t ble_hs_hci_version;
41 
42 /**
43  * The number of available ACL transmit buffers on the controller.  This
44  * variable must only be accessed while the host mutex is locked.
45  */
46 uint16_t ble_hs_hci_avail_pkts;
47 
48 #if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS)
49 static ble_hs_hci_phony_ack_fn *ble_hs_hci_phony_ack_cb;
50 #endif
51 
52 #if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS)
53 void
ble_hs_hci_set_phony_ack_cb(ble_hs_hci_phony_ack_fn * cb)54 ble_hs_hci_set_phony_ack_cb(ble_hs_hci_phony_ack_fn *cb)
55 {
56     ble_hs_hci_phony_ack_cb = cb;
57 }
58 #endif
59 
60 static void
ble_hs_hci_lock(void)61 ble_hs_hci_lock(void)
62 {
63     int rc;
64 
65     rc = ble_npl_mutex_pend(&ble_hs_hci_mutex, BLE_NPL_TIME_FOREVER);
66     BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
67 }
68 
69 static void
ble_hs_hci_unlock(void)70 ble_hs_hci_unlock(void)
71 {
72     int rc;
73 
74     rc = ble_npl_mutex_release(&ble_hs_hci_mutex);
75     BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
76 }
77 
78 int
ble_hs_hci_set_buf_sz(uint16_t pktlen,uint16_t max_pkts)79 ble_hs_hci_set_buf_sz(uint16_t pktlen, uint16_t max_pkts)
80 {
81     if (pktlen == 0 || max_pkts == 0) {
82         return BLE_HS_EINVAL;
83     }
84 
85     ble_hs_hci_buf_sz = pktlen;
86     ble_hs_hci_max_pkts = max_pkts;
87     ble_hs_hci_avail_pkts = max_pkts;
88 
89     return 0;
90 }
91 
92 /**
93  * Increases the count of available controller ACL buffers.
94  */
95 void
ble_hs_hci_add_avail_pkts(uint16_t delta)96 ble_hs_hci_add_avail_pkts(uint16_t delta)
97 {
98     BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
99 
100     if (ble_hs_hci_avail_pkts + delta > UINT16_MAX) {
101         ble_hs_sched_reset(BLE_HS_ECONTROLLER);
102     } else {
103         ble_hs_hci_avail_pkts += delta;
104     }
105 }
106 
107 static int
ble_hs_hci_rx_cmd_complete(uint8_t event_code,uint8_t * data,int len,struct ble_hs_hci_ack * out_ack)108 ble_hs_hci_rx_cmd_complete(uint8_t event_code, uint8_t *data, int len,
109                            struct ble_hs_hci_ack *out_ack)
110 {
111     uint16_t opcode;
112     uint8_t *params;
113     uint8_t params_len;
114     uint8_t num_pkts;
115 
116     if (len < BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN) {
117         return BLE_HS_ECONTROLLER;
118     }
119 
120     num_pkts = data[2];
121     opcode = get_le16(data + 3);
122     params = data + 5;
123 
124     /* XXX: Process num_pkts field. */
125     (void)num_pkts;
126 
127     out_ack->bha_opcode = opcode;
128 
129     params_len = len - BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN;
130     if (params_len > 0) {
131         out_ack->bha_status = BLE_HS_HCI_ERR(params[0]);
132     } else if (opcode == BLE_HCI_OPCODE_NOP) {
133         out_ack->bha_status = 0;
134     } else {
135         out_ack->bha_status = BLE_HS_ECONTROLLER;
136     }
137 
138     /* Don't include the status byte in the parameters blob. */
139     if (params_len > 1) {
140         out_ack->bha_params = params + 1;
141         out_ack->bha_params_len = params_len - 1;
142     } else {
143         out_ack->bha_params = NULL;
144         out_ack->bha_params_len = 0;
145     }
146 
147     return 0;
148 }
149 
150 static int
ble_hs_hci_rx_cmd_status(uint8_t event_code,uint8_t * data,int len,struct ble_hs_hci_ack * out_ack)151 ble_hs_hci_rx_cmd_status(uint8_t event_code, uint8_t *data, int len,
152                          struct ble_hs_hci_ack *out_ack)
153 {
154     uint16_t opcode;
155     uint8_t num_pkts;
156     uint8_t status;
157 
158     if (len < BLE_HCI_EVENT_CMD_STATUS_LEN) {
159         return BLE_HS_ECONTROLLER;
160     }
161 
162     status = data[2];
163     num_pkts = data[3];
164     opcode = get_le16(data + 4);
165 
166     /* XXX: Process num_pkts field. */
167     (void)num_pkts;
168 
169     out_ack->bha_opcode = opcode;
170     out_ack->bha_params = NULL;
171     out_ack->bha_params_len = 0;
172     out_ack->bha_status = BLE_HS_HCI_ERR(status);
173 
174     return 0;
175 }
176 
177 static int
ble_hs_hci_process_ack(uint16_t expected_opcode,uint8_t * params_buf,uint8_t params_buf_len,struct ble_hs_hci_ack * out_ack)178 ble_hs_hci_process_ack(uint16_t expected_opcode,
179                        uint8_t *params_buf, uint8_t params_buf_len,
180                        struct ble_hs_hci_ack *out_ack)
181 {
182     uint8_t event_code;
183     uint8_t param_len;
184     uint8_t event_len;
185     int rc;
186 
187     BLE_HS_DBG_ASSERT(ble_hs_hci_ack != NULL);
188 
189     /* Count events received */
190     STATS_INC(ble_hs_stats, hci_event);
191 
192     /* Display to console */
193     ble_hs_dbg_event_disp(ble_hs_hci_ack);
194 
195     event_code = ble_hs_hci_ack[0];
196     param_len = ble_hs_hci_ack[1];
197     event_len = param_len + 2;
198 
199     /* Clear ack fields up front to silence spurious gcc warnings. */
200     memset(out_ack, 0, sizeof *out_ack);
201 
202     switch (event_code) {
203     case BLE_HCI_EVCODE_COMMAND_COMPLETE:
204         rc = ble_hs_hci_rx_cmd_complete(event_code, ble_hs_hci_ack,
205                                          event_len, out_ack);
206         break;
207 
208     case BLE_HCI_EVCODE_COMMAND_STATUS:
209         rc = ble_hs_hci_rx_cmd_status(event_code, ble_hs_hci_ack,
210                                        event_len, out_ack);
211         break;
212 
213     default:
214         BLE_HS_DBG_ASSERT(0);
215         rc = BLE_HS_EUNKNOWN;
216         break;
217     }
218 
219     if (rc == 0) {
220         if (params_buf == NULL) {
221             out_ack->bha_params_len = 0;
222         } else {
223             if (out_ack->bha_params_len > params_buf_len) {
224                 out_ack->bha_params_len = params_buf_len;
225                 rc = BLE_HS_ECONTROLLER;
226             }
227             memcpy(params_buf, out_ack->bha_params, out_ack->bha_params_len);
228         }
229         out_ack->bha_params = params_buf;
230 
231         if (out_ack->bha_opcode != expected_opcode) {
232             rc = BLE_HS_ECONTROLLER;
233         }
234     }
235 
236     if (rc != 0) {
237         STATS_INC(ble_hs_stats, hci_invalid_ack);
238     }
239 
240     return rc;
241 }
242 
243 static int
ble_hs_hci_wait_for_ack(void)244 ble_hs_hci_wait_for_ack(void)
245 {
246     int rc;
247 
248 #if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS)
249     if (ble_hs_hci_phony_ack_cb == NULL) {
250         rc = BLE_HS_ETIMEOUT_HCI;
251     } else {
252         ble_hs_hci_ack =
253             ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
254         BLE_HS_DBG_ASSERT(ble_hs_hci_ack != NULL);
255         rc = ble_hs_hci_phony_ack_cb(ble_hs_hci_ack, 260);
256     }
257 #else
258     rc = ble_npl_sem_pend(&ble_hs_hci_sem,
259                      ble_npl_time_ms_to_ticks32(BLE_HCI_CMD_TIMEOUT_MS));
260     switch (rc) {
261     case 0:
262         BLE_HS_DBG_ASSERT(ble_hs_hci_ack != NULL);
263 
264 #if BLE_MONITOR
265         ble_monitor_send(BLE_MONITOR_OPCODE_EVENT_PKT, ble_hs_hci_ack,
266                          ble_hs_hci_ack[1] + BLE_HCI_EVENT_HDR_LEN);
267 #endif
268 
269         break;
270     case OS_TIMEOUT:
271         rc = BLE_HS_ETIMEOUT_HCI;
272         STATS_INC(ble_hs_stats, hci_timeout);
273         break;
274     default:
275         rc = BLE_HS_EOS;
276         break;
277     }
278 #endif
279 
280     return rc;
281 }
282 
283 int
ble_hs_hci_cmd_tx(uint16_t opcode,void * cmd,uint8_t cmd_len,void * evt_buf,uint8_t evt_buf_len,uint8_t * out_evt_buf_len)284 ble_hs_hci_cmd_tx(uint16_t opcode, void *cmd, uint8_t cmd_len,
285                   void *evt_buf, uint8_t evt_buf_len,
286                   uint8_t *out_evt_buf_len)
287 {
288     struct ble_hs_hci_ack ack;
289     int rc;
290 
291     BLE_HS_DBG_ASSERT(ble_hs_hci_ack == NULL);
292     ble_hs_hci_lock();
293 
294     rc = ble_hs_hci_cmd_send_buf(opcode, cmd, cmd_len);
295     if (rc != 0) {
296         goto done;
297     }
298 
299     rc = ble_hs_hci_wait_for_ack();
300     if (rc != 0) {
301         ble_hs_sched_reset(rc);
302         goto done;
303     }
304 
305     rc = ble_hs_hci_process_ack(opcode, evt_buf, evt_buf_len, &ack);
306     if (rc != 0) {
307         ble_hs_sched_reset(rc);
308         goto done;
309     }
310 
311     if (out_evt_buf_len != NULL) {
312         *out_evt_buf_len = ack.bha_params_len;
313     }
314 
315     rc = ack.bha_status;
316 
317 done:
318     if (ble_hs_hci_ack != NULL) {
319         ble_hci_trans_buf_free(ble_hs_hci_ack);
320         ble_hs_hci_ack = NULL;
321     }
322 
323     ble_hs_hci_unlock();
324     return rc;
325 }
326 
327 int
ble_hs_hci_cmd_tx_empty_ack(uint16_t opcode,void * cmd,uint8_t cmd_len)328 ble_hs_hci_cmd_tx_empty_ack(uint16_t opcode, void *cmd, uint8_t cmd_len)
329 {
330     int rc;
331 
332     rc = ble_hs_hci_cmd_tx(opcode, cmd, cmd_len, NULL, 0, NULL);
333     if (rc != 0) {
334         return rc;
335     }
336 
337     return 0;
338 }
339 
340 void
ble_hs_hci_rx_ack(uint8_t * ack_ev)341 ble_hs_hci_rx_ack(uint8_t *ack_ev)
342 {
343     if (ble_npl_sem_get_count(&ble_hs_hci_sem) > 0) {
344         /* This ack is unexpected; ignore it. */
345         ble_hci_trans_buf_free(ack_ev);
346         return;
347     }
348     BLE_HS_DBG_ASSERT(ble_hs_hci_ack == NULL);
349 
350     /* Unblock the application now that the HCI command buffer is populated
351      * with the acknowledgement.
352      */
353     ble_hs_hci_ack = ack_ev;
354     ble_npl_sem_release(&ble_hs_hci_sem);
355 }
356 
357 int
ble_hs_hci_rx_evt(uint8_t * hci_ev,void * arg)358 ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg)
359 {
360     int enqueue;
361 
362     BLE_HS_DBG_ASSERT(hci_ev != NULL);
363 
364     switch (hci_ev[0]) {
365     case BLE_HCI_EVCODE_COMMAND_COMPLETE:
366     case BLE_HCI_EVCODE_COMMAND_STATUS:
367         if (hci_ev[3] == 0 && hci_ev[4] == 0) {
368             enqueue = 1;
369         } else {
370             ble_hs_hci_rx_ack(hci_ev);
371             enqueue = 0;
372         }
373         break;
374 
375     default:
376         enqueue = 1;
377         break;
378     }
379 
380     if (enqueue) {
381         ble_hs_enqueue_hci_event(hci_ev);
382     }
383 
384     return 0;
385 }
386 
387 /**
388  * Calculates the largest ACL payload that the controller can accept.  This is
389  * everything in an ACL data packet except for the ACL header.
390  */
391 static uint16_t
ble_hs_hci_max_acl_payload_sz(void)392 ble_hs_hci_max_acl_payload_sz(void)
393 {
394     return ble_hs_hci_buf_sz - BLE_HCI_DATA_HDR_SZ;
395 }
396 
397 /**
398  * Allocates an mbuf to contain an outgoing ACL data fragment.
399  */
400 static struct os_mbuf *
ble_hs_hci_frag_alloc(uint16_t frag_size,void * arg)401 ble_hs_hci_frag_alloc(uint16_t frag_size, void *arg)
402 {
403     return ble_hs_mbuf_acl_pkt();
404 }
405 
406 static struct os_mbuf *
ble_hs_hci_acl_hdr_prepend(struct os_mbuf * om,uint16_t handle,uint8_t pb_flag)407 ble_hs_hci_acl_hdr_prepend(struct os_mbuf *om, uint16_t handle,
408                            uint8_t pb_flag)
409 {
410     struct hci_data_hdr hci_hdr;
411     struct os_mbuf *om2;
412 
413     hci_hdr.hdh_handle_pb_bc =
414         ble_hs_hci_util_handle_pb_bc_join(handle, pb_flag, 0);
415     put_le16(&hci_hdr.hdh_len, OS_MBUF_PKTHDR(om)->omp_len);
416 
417     om2 = os_mbuf_prepend(om, sizeof hci_hdr);
418     if (om2 == NULL) {
419         return NULL;
420     }
421 
422     om = om2;
423     om = os_mbuf_pullup(om, sizeof hci_hdr);
424     if (om == NULL) {
425         return NULL;
426     }
427 
428     memcpy(om->om_data, &hci_hdr, sizeof hci_hdr);
429 
430 #if !BLE_MONITOR
431     BLE_HS_LOG(DEBUG, "host tx hci data; handle=%d length=%d\n", handle,
432                get_le16(&hci_hdr.hdh_len));
433 #endif
434 
435     return om;
436 }
437 
438 int
ble_hs_hci_acl_tx_now(struct ble_hs_conn * conn,struct os_mbuf ** om)439 ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om)
440 {
441     struct os_mbuf *txom;
442     struct os_mbuf *frag;
443     uint8_t pb;
444     int rc;
445 
446     BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
447 
448     txom = *om;
449     *om = NULL;
450 
451     if (!(conn->bhc_flags & BLE_HS_CONN_F_TX_FRAG)) {
452         /* The first fragment uses the first-non-flush packet boundary value.
453          * After sending the first fragment, pb gets set appropriately for all
454          * subsequent fragments in this packet.
455          */
456         pb = BLE_HCI_PB_FIRST_NON_FLUSH;
457     } else {
458         pb = BLE_HCI_PB_MIDDLE;
459     }
460 
461     /* Send fragments until the entire packet has been sent. */
462     while (txom != NULL && ble_hs_hci_avail_pkts > 0) {
463         frag = mem_split_frag(&txom, ble_hs_hci_max_acl_payload_sz(),
464                               ble_hs_hci_frag_alloc, NULL);
465 
466         frag = ble_hs_hci_acl_hdr_prepend(frag, conn->bhc_handle, pb);
467         if (frag == NULL) {
468             rc = BLE_HS_ENOMEM;
469             goto err;
470         }
471 
472 #if !BLE_MONITOR
473         BLE_HS_LOG(DEBUG, "ble_hs_hci_acl_tx(): ");
474         ble_hs_log_mbuf(frag);
475         BLE_HS_LOG(DEBUG, "\n");
476 #endif
477 
478         rc = ble_hs_tx_data(frag);
479         if (rc != 0) {
480             goto err;
481         }
482 
483         /* If any fragments remain, they should be marked as 'middle'
484          * fragments.
485          */
486         conn->bhc_flags |= BLE_HS_CONN_F_TX_FRAG;
487         pb = BLE_HCI_PB_MIDDLE;
488 
489         /* Account for the controller buf that will hold the txed fragment. */
490         conn->bhc_outstanding_pkts++;
491         ble_hs_hci_avail_pkts--;
492     }
493 
494     if (txom != NULL) {
495         /* The controller couldn't accommodate some or all of the packet. */
496         *om = txom;
497         return BLE_HS_EAGAIN;
498     }
499 
500     /* The entire packet was transmitted. */
501     conn->bhc_flags &= ~BLE_HS_CONN_F_TX_FRAG;
502 
503     return 0;
504 
505 err:
506     BLE_HS_DBG_ASSERT(rc != 0);
507 
508     conn->bhc_flags &= ~BLE_HS_CONN_F_TX_FRAG;
509     os_mbuf_free_chain(txom);
510     return rc;
511 }
512 
513 /**
514  * Transmits an HCI ACL data packet.  This function consumes the supplied mbuf,
515  * regardless of the outcome.
516  *
517  * @return                      0 on success;
518  *                              BLE_HS_EAGAIN if the packet could not be sent
519  *                                  in its entirety due to controller buffer
520  *                                  exhaustion.  The unsent data is pointed to
521  *                                  by the `om` parameter.
522  *                              A BLE host core return code on unexpected
523  *                                  error.
524  *
525  */
526 int
ble_hs_hci_acl_tx(struct ble_hs_conn * conn,struct os_mbuf ** om)527 ble_hs_hci_acl_tx(struct ble_hs_conn *conn, struct os_mbuf **om)
528 {
529     BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
530 
531     /* If this conn is already backed up, don't even try to send. */
532     if (STAILQ_FIRST(&conn->bhc_tx_q) != NULL) {
533         return BLE_HS_EAGAIN;
534     }
535 
536     return ble_hs_hci_acl_tx_now(conn, om);
537 }
538 
539 void
ble_hs_hci_set_le_supported_feat(uint32_t feat)540 ble_hs_hci_set_le_supported_feat(uint32_t feat)
541 {
542     ble_hs_hci_sup_feat = feat;
543 }
544 
545 uint32_t
ble_hs_hci_get_le_supported_feat(void)546 ble_hs_hci_get_le_supported_feat(void)
547 {
548     return ble_hs_hci_sup_feat;
549 }
550 
551 void
ble_hs_hci_set_hci_version(uint8_t hci_version)552 ble_hs_hci_set_hci_version(uint8_t hci_version)
553 {
554     ble_hs_hci_version = hci_version;
555 }
556 
557 uint8_t
ble_hs_hci_get_hci_version(void)558 ble_hs_hci_get_hci_version(void)
559 {
560     return ble_hs_hci_version;
561 }
562 
563 void
ble_hs_hci_init(void)564 ble_hs_hci_init(void)
565 {
566     int rc;
567 
568     rc = ble_npl_sem_init(&ble_hs_hci_sem, 0);
569     BLE_HS_DBG_ASSERT_EVAL(rc == 0);
570 
571     rc = ble_npl_mutex_init(&ble_hs_hci_mutex);
572     BLE_HS_DBG_ASSERT_EVAL(rc == 0);
573 }
574