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