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
20 /*
21 * Provides HCI transport over sockets. Either over
22 * TCP sockets, or Linux bluetooth socket.
23 *
24 * E.g. to connect to TCP target, start in another window
25 * socat -x PIPE:/dev/ttyACM1 TCP4-LISTEN:14433,fork,reuseaddr
26 * When building this package, set BLE_SOCK_USE_TCP=1 and
27 * BLE_SOCK_TCP_PORT controls the target port this transport
28 * connects to.
29 *
30 * To use Linux Bluetooth sockets, create an interface:
31 * sudo hciattach -r -n /dev/ttyUSB0 any 57600
32 * And build this package with BLE_SOCK_USE_LINUX_BLUE=1,
33 * BLE_SOCK_LINUX_DEV=<interface index of the target interface>
34 *
35 */
36 #include "syscfg/syscfg.h"
37
38 #include <assert.h>
39 #include <string.h>
40 #include <stdio.h>
41 #include <stdint.h>
42 #include <stdlib.h>
43 #include <sys/types.h>
44 #include <sys/uio.h>
45 #include <unistd.h>
46 #include <sys/socket.h>
47
48 #if MYNEWT_VAL(BLE_SOCK_USE_TCP)
49 #include <sys/errno.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
52 #endif
53
54 #if MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
55 #include <sys/errno.h>
56 #define BTPROTO_HCI 1
57 #define HCI_CHANNEL_RAW 0
58 #define HCI_CHANNEL_USER 1
59 #define HCIDEVUP _IOW('H', 201, int)
60 #define HCIDEVDOWN _IOW('H', 202, int)
61 #define HCIDEVRESET _IOW('H', 203, int)
62 #define HCIGETDEVLIST _IOR('H', 210, int)
63
64 struct sockaddr_hci {
65 sa_family_t hci_family;
66 unsigned short hci_dev;
67 unsigned short hci_channel;
68 };
69 #endif
70
71 #include <fcntl.h>
72 #include <sys/ioctl.h>
73
74 #include "sysinit/sysinit.h"
75 #include "os/os.h"
76 #include "mem/mem.h"
77
78 #include "stats/stats.h"
79
80 /* BLE */
81 #include "nimble/ble.h"
82 #include "nimble/nimble_opt.h"
83 #include "nimble/hci_common.h"
84 #include "nimble/nimble_npl.h"
85 #include "nimble/ble_hci_trans.h"
86 #include "socket/ble_hci_socket.h"
87
88 /***
89 * NOTES:
90 * The UART HCI transport doesn't use event buffer priorities. All incoming
91 * and outgoing events use buffers from the same pool.
92 *
93 * The "skip" definitions are here so that when buffers cannot be allocated,
94 * the command or acl packets are simply skipped so that the HCI interface
95 * does not lose synchronization and resets dont (necessarily) occur.
96 */
97
98 STATS_SECT_START(hci_sock_stats)
99 STATS_SECT_ENTRY(imsg)
100 STATS_SECT_ENTRY(icmd)
101 STATS_SECT_ENTRY(ievt)
102 STATS_SECT_ENTRY(iacl)
103 STATS_SECT_ENTRY(ibytes)
104 STATS_SECT_ENTRY(ierr)
105 STATS_SECT_ENTRY(imem)
106 STATS_SECT_ENTRY(omsg)
107 STATS_SECT_ENTRY(oacl)
108 STATS_SECT_ENTRY(ocmd)
109 STATS_SECT_ENTRY(oevt)
110 STATS_SECT_ENTRY(obytes)
111 STATS_SECT_ENTRY(oerr)
112 STATS_SECT_END
113
114 STATS_SECT_DECL(hci_sock_stats) hci_sock_stats;
115 STATS_NAME_START(hci_sock_stats)
116 STATS_NAME(hci_sock_stats, imsg)
117 STATS_NAME(hci_sock_stats, icmd)
118 STATS_NAME(hci_sock_stats, ievt)
119 STATS_NAME(hci_sock_stats, iacl)
120 STATS_NAME(hci_sock_stats, ibytes)
121 STATS_NAME(hci_sock_stats, ierr)
122 STATS_NAME(hci_sock_stats, imem)
123 STATS_NAME(hci_sock_stats, omsg)
124 STATS_NAME(hci_sock_stats, oacl)
125 STATS_NAME(hci_sock_stats, ocmd)
126 STATS_NAME(hci_sock_stats, oevt)
127 STATS_NAME(hci_sock_stats, obytes)
128 STATS_NAME(hci_sock_stats, oerr)
129 STATS_NAME_END(hci_sock_stats)
130
131 /***
132 * NOTES:
133 * The "skip" definitions are here so that when buffers cannot be allocated,
134 * the command or acl packets are simply skipped so that the HCI interface
135 * does not lose synchronization and resets dont (necessarily) occur.
136 */
137 #define BLE_HCI_UART_H4_NONE 0x00
138 #define BLE_HCI_UART_H4_CMD 0x01
139 #define BLE_HCI_UART_H4_ACL 0x02
140 #define BLE_HCI_UART_H4_SCO 0x03
141 #define BLE_HCI_UART_H4_EVT 0x04
142 #define BLE_HCI_UART_H4_SYNC_LOSS 0x80
143 #define BLE_HCI_UART_H4_SKIP_CMD 0x81
144 #define BLE_HCI_UART_H4_SKIP_ACL 0x82
145
146 #if MYNEWT
147
148 #define BLE_SOCK_STACK_SIZE \
149 OS_STACK_ALIGN(MYNEWT_VAL(BLE_SOCK_STACK_SIZE))
150
151 struct os_task ble_sock_task;
152
153 #endif
154
155 static struct os_mempool ble_hci_sock_evt_hi_pool;
156 static os_membuf_t ble_hci_sock_evt_hi_buf[
157 OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
158 MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
159 ];
160
161 static struct os_mempool ble_hci_sock_evt_lo_pool;
162 static os_membuf_t ble_hci_sock_evt_lo_buf[
163 OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
164 MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
165 ];
166
167 static struct os_mempool ble_hci_sock_cmd_pool;
168 static os_membuf_t ble_hci_sock_cmd_buf[
169 OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ)
170 ];
171
172 static struct os_mempool ble_hci_sock_acl_pool;
173 static struct os_mbuf_pool ble_hci_sock_acl_mbuf_pool;
174
175 #define ACL_BLOCK_SIZE OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) \
176 + BLE_MBUF_MEMBLOCK_OVERHEAD \
177 + BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
178 /*
179 * The MBUF payload size must accommodate the HCI data header size plus the
180 * maximum ACL data packet length. The ACL block size is the size of the
181 * mbufs we will allocate.
182 */
183
184 static os_membuf_t ble_hci_sock_acl_buf[
185 OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_ACL_BUF_COUNT),
186 ACL_BLOCK_SIZE)
187 ];
188
189 static ble_hci_trans_rx_cmd_fn *ble_hci_sock_rx_cmd_cb;
190 static void *ble_hci_sock_rx_cmd_arg;
191 static ble_hci_trans_rx_acl_fn *ble_hci_sock_rx_acl_cb;
192 static void *ble_hci_sock_rx_acl_arg;
193
194 static struct ble_hci_sock_state {
195 int sock;
196 struct ble_npl_eventq evq;
197 struct ble_npl_event ev;
198 struct ble_npl_callout timer;
199
200 uint16_t rx_off;
201 uint8_t rx_data[512];
202 } ble_hci_sock_state;
203
204 #if MYNEWT_VAL(BLE_SOCK_USE_TCP)
205 static int s_ble_hci_device = MYNEWT_VAL(BLE_SOCK_TCP_PORT);
206 #elif MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
207 static int s_ble_hci_device = MYNEWT_VAL(BLE_SOCK_LINUX_DEV);
208 #endif
209
210 /**
211 * Allocates a buffer (mbuf) for ACL operation.
212 *
213 * @return The allocated buffer on success;
214 * NULL on buffer exhaustion.
215 */
216 static struct os_mbuf *
ble_hci_trans_acl_buf_alloc(void)217 ble_hci_trans_acl_buf_alloc(void)
218 {
219 struct os_mbuf *m;
220
221 /*
222 * XXX: note that for host only there would be no need to allocate
223 * a user header. Address this later.
224 */
225 m = os_mbuf_get_pkthdr(&ble_hci_sock_acl_mbuf_pool,
226 sizeof(struct ble_mbuf_hdr));
227 return m;
228 }
229
230 static int
ble_hci_sock_acl_tx(struct os_mbuf * om)231 ble_hci_sock_acl_tx(struct os_mbuf *om)
232 {
233 struct msghdr msg;
234 struct iovec iov[8];
235 int i;
236 struct os_mbuf *m;
237 uint8_t ch;
238
239 memset(&msg, 0, sizeof(msg));
240 memset(iov, 0, sizeof(iov));
241
242 msg.msg_iov = iov;
243
244 ch = BLE_HCI_UART_H4_ACL;
245 iov[0].iov_len = 1;
246 iov[0].iov_base = &ch;
247 i = 1;
248 for (m = om; m; m = SLIST_NEXT(m, om_next)) {
249 iov[i].iov_base = m->om_data;
250 iov[i].iov_len = m->om_len;
251 i++;
252 }
253 msg.msg_iovlen = i;
254
255 STATS_INC(hci_sock_stats, omsg);
256 STATS_INC(hci_sock_stats, oacl);
257 STATS_INCN(hci_sock_stats, obytes, OS_MBUF_PKTLEN(om) + 1);
258 i = sendmsg(ble_hci_sock_state.sock, &msg, 0);
259 os_mbuf_free_chain(om);
260 if (i != OS_MBUF_PKTLEN(om) + 1) {
261 if (i < 0) {
262 dprintf(1, "sendmsg() failed : %d\n", errno);
263 } else {
264 dprintf(1, "sendmsg() partial write: %d\n", i);
265 }
266 STATS_INC(hci_sock_stats, oerr);
267 return BLE_ERR_MEM_CAPACITY;
268 }
269 return 0;
270 }
271
272 static int
ble_hci_sock_cmdevt_tx(uint8_t * hci_ev,uint8_t h4_type)273 ble_hci_sock_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type)
274 {
275 struct msghdr msg;
276 struct iovec iov[8];
277 int len;
278 int i;
279 uint8_t ch;
280
281 memset(&msg, 0, sizeof(msg));
282 memset(iov, 0, sizeof(iov));
283
284 msg.msg_iov = iov;
285 msg.msg_iovlen = 2;
286
287 ch = h4_type;
288 iov[0].iov_len = 1;
289 iov[0].iov_base = &ch;
290 iov[1].iov_base = hci_ev;
291 if (h4_type == BLE_HCI_UART_H4_CMD) {
292 len = BLE_HCI_CMD_HDR_LEN + hci_ev[2];
293 STATS_INC(hci_sock_stats, ocmd);
294 } else if (h4_type == BLE_HCI_UART_H4_EVT) {
295 len = BLE_HCI_EVENT_HDR_LEN + hci_ev[1];
296 STATS_INC(hci_sock_stats, oevt);
297 } else {
298 assert(0);
299 }
300 iov[1].iov_len = len;
301
302 STATS_INC(hci_sock_stats, omsg);
303 STATS_INCN(hci_sock_stats, obytes, len + 1);
304
305 i = sendmsg(ble_hci_sock_state.sock, &msg, 0);
306 ble_hci_trans_buf_free(hci_ev);
307 if (i != len + 1) {
308 if (i < 0) {
309 dprintf(1, "sendmsg() failed : %d\n", errno);
310 } else {
311 dprintf(1, "sendmsg() partial write: %d\n", i);
312 }
313 STATS_INC(hci_sock_stats, oerr);
314 return BLE_ERR_MEM_CAPACITY;
315 }
316
317 return 0;
318 }
319
320 static int
ble_hci_sock_rx_msg(void)321 ble_hci_sock_rx_msg(void)
322 {
323 struct ble_hci_sock_state *bhss;
324 int len;
325 struct os_mbuf *m;
326 uint8_t *data;
327 int sr;
328 int rc;
329
330 bhss = &ble_hci_sock_state;
331 if (bhss->sock < 0) {
332 return -1;
333 }
334 len = read(bhss->sock, bhss->rx_data + bhss->rx_off,
335 sizeof(bhss->rx_data) - bhss->rx_off);
336 if (len < 0) {
337 return -2;
338 }
339 if (len == 0) {
340 return -1;
341 }
342 bhss->rx_off += len;
343 STATS_INCN(hci_sock_stats, ibytes, len);
344
345 while (bhss->rx_off > 0) {
346 switch (bhss->rx_data[0]) {
347 #if MYNEWT_VAL(BLE_DEVICE)
348 case BLE_HCI_UART_H4_CMD:
349 if (bhss->rx_off < BLE_HCI_CMD_HDR_LEN) {
350 return -1;
351 }
352 len = 1 + BLE_HCI_CMD_HDR_LEN + bhss->rx_data[3];
353 if (bhss->rx_off < len) {
354 return -1;
355 }
356 STATS_INC(hci_sock_stats, imsg);
357 STATS_INC(hci_sock_stats, icmd);
358 data = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
359 if (!data) {
360 STATS_INC(hci_sock_stats, ierr);
361 break;
362 }
363 memcpy(data, &bhss->rx_data[1], len - 1);
364 OS_ENTER_CRITICAL(sr);
365 rc = ble_hci_sock_rx_cmd_cb(data, ble_hci_sock_rx_cmd_arg);
366 OS_EXIT_CRITICAL(sr);
367 if (rc) {
368 ble_hci_trans_buf_free(data);
369 STATS_INC(hci_sock_stats, ierr);
370 break;
371 }
372 break;
373 #endif
374 #if MYNEWT_VAL(BLE_HOST)
375 case BLE_HCI_UART_H4_EVT:
376 if (bhss->rx_off < BLE_HCI_EVENT_HDR_LEN) {
377 return -1;
378 }
379 len = 1 + BLE_HCI_EVENT_HDR_LEN + bhss->rx_data[2];
380 if (bhss->rx_off < len) {
381 return -1;
382 }
383 STATS_INC(hci_sock_stats, imsg);
384 STATS_INC(hci_sock_stats, ievt);
385 data = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
386 if (!data) {
387 STATS_INC(hci_sock_stats, ierr);
388 break;
389 }
390 memcpy(data, &bhss->rx_data[1], len - 1);
391 OS_ENTER_CRITICAL(sr);
392 rc = ble_hci_sock_rx_cmd_cb(data, ble_hci_sock_rx_cmd_arg);
393 OS_EXIT_CRITICAL(sr);
394 if (rc) {
395 ble_hci_trans_buf_free(data);
396 STATS_INC(hci_sock_stats, ierr);
397 return 0;
398 }
399 break;
400 #endif
401 case BLE_HCI_UART_H4_ACL:
402 if (bhss->rx_off < BLE_HCI_DATA_HDR_SZ) {
403 return -1;
404 }
405 len = 1 + BLE_HCI_DATA_HDR_SZ + (bhss->rx_data[4] << 8) +
406 bhss->rx_data[3];
407 if (bhss->rx_off < len) {
408 return -1;
409 }
410 STATS_INC(hci_sock_stats, imsg);
411 STATS_INC(hci_sock_stats, iacl);
412 m = ble_hci_trans_acl_buf_alloc();
413 if (!m) {
414 STATS_INC(hci_sock_stats, imem);
415 break;
416 }
417 if (os_mbuf_append(m, &bhss->rx_data[1], len - 1)) {
418 STATS_INC(hci_sock_stats, imem);
419 os_mbuf_free_chain(m);
420 break;
421 }
422 OS_ENTER_CRITICAL(sr);
423 ble_hci_sock_rx_acl_cb(m, ble_hci_sock_rx_acl_arg);
424 OS_EXIT_CRITICAL(sr);
425 break;
426 default:
427 STATS_INC(hci_sock_stats, ierr);
428 break;
429 }
430 memmove(bhss->rx_data, &bhss->rx_data[len], bhss->rx_off - len);
431 bhss->rx_off -= len;
432 }
433 return 0;
434 }
435
436 static void
ble_hci_sock_rx_ev(struct ble_npl_event * ev)437 ble_hci_sock_rx_ev(struct ble_npl_event *ev)
438 {
439 int rc;
440 ble_npl_time_t timeout;
441
442 rc = ble_hci_sock_rx_msg();
443 if (rc == 0) {
444 ble_npl_eventq_put(&ble_hci_sock_state.evq, &ble_hci_sock_state.ev);
445 } else {
446 rc = ble_npl_time_ms_to_ticks(10, &timeout);
447 ble_npl_callout_reset(&ble_hci_sock_state.timer, timeout);
448 }
449 }
450
451 #if MYNEWT_VAL(BLE_SOCK_USE_TCP)
452 static int
ble_hci_sock_config(void)453 ble_hci_sock_config(void)
454 {
455 struct ble_hci_sock_state *bhss = &ble_hci_sock_state;
456 struct sockaddr_in sin;
457 ble_npl_time_t timeout;
458 int s;
459 int rc;
460
461 memset(&sin, 0, sizeof(sin));
462 sin.sin_family = AF_INET;
463 sin.sin_port = htons(s_ble_hci_device);
464 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
465 #ifdef MN_OSX
466 sin.sin_len = sizeof(sin);
467 #endif
468
469 #if 0
470 if (bhss->sock >= 0) {
471 close(bhss->sock);
472 bhss->sock = -1;
473 }
474 #endif
475 if (bhss->sock < 0) {
476 s = socket(PF_INET, SOCK_STREAM, 0);
477 if (s < 0) {
478 goto err;
479 }
480
481 rc = connect(s, (struct sockaddr *)&sin, sizeof(sin));
482 if (rc) {
483 dprintf(1, "connect() failed: %d\n", errno);
484 goto err;
485 }
486
487 rc = 1;
488
489 rc = ioctl(s, FIONBIO, (char *)&rc);
490 if (rc) {
491 goto err;
492 }
493 bhss->sock = s;
494 }
495 rc = ble_npl_time_ms_to_ticks(10, &timeout);
496 if (rc) {
497 goto err;
498 }
499 ble_npl_callout_reset(&ble_hci_sock_state.timer, timeout);
500
501 return 0;
502 err:
503 if (s >= 0) {
504 close(s);
505 }
506 return BLE_ERR_HW_FAIL;
507 }
508 #endif
509
510 #if MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
511 static int
ble_hci_sock_config(void)512 ble_hci_sock_config(void)
513 {
514 struct sockaddr_hci shci;
515 int s;
516 int rc;
517 ble_npl_time_t timeout;
518
519 memset(&shci, 0, sizeof(shci));
520 shci.hci_family = AF_BLUETOOTH;
521 shci.hci_dev = s_ble_hci_device;
522 shci.hci_channel = HCI_CHANNEL_USER;
523
524 if (ble_hci_sock_state.sock >= 0) {
525 close(ble_hci_sock_state.sock);
526 ble_hci_sock_state.sock = -1;
527 }
528
529 s = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
530 if (s < 0) {
531 dprintf(1, "socket() failed %d\n", errno);
532 goto err;
533 }
534
535 /*
536 * HCI User Channel requires exclusive access to the device.
537 * The device has to be down at the time of binding.
538 */
539 ioctl(s, HCIDEVDOWN, shci.hci_dev);
540
541 rc = bind(s, (struct sockaddr *)&shci, sizeof(shci));
542 if (rc) {
543 dprintf(1, "bind() failed %d\n", errno);
544 goto err;
545 }
546
547 rc = 1;
548
549 rc = ioctl(s, FIONBIO, (char *)&rc);
550 if (rc) {
551 goto err;
552 }
553 ble_hci_sock_state.sock = s;
554
555 rc = ble_npl_time_ms_to_ticks(10, &timeout);
556 if (rc) {
557 goto err;
558 }
559 ble_npl_callout_reset(&ble_hci_sock_state.timer, timeout);
560
561 return 0;
562 err:
563 if (s >= 0) {
564 close(s);
565 }
566 return BLE_ERR_HW_FAIL;
567 }
568 #endif
569 /**
570 * Sends an HCI event from the controller to the host.
571 *
572 * @param cmd The HCI event to send. This buffer must be
573 * allocated via ble_hci_trans_buf_alloc().
574 *
575 * @return 0 on success;
576 * A BLE_ERR_[...] error code on failure.
577 */
578 int
ble_hci_trans_ll_evt_tx(uint8_t * cmd)579 ble_hci_trans_ll_evt_tx(uint8_t *cmd)
580 {
581 return ble_hci_sock_cmdevt_tx(cmd, BLE_HCI_UART_H4_EVT);
582 }
583
584 /**
585 * Sends ACL data from controller to host.
586 *
587 * @param om The ACL data packet to send.
588 *
589 * @return 0 on success;
590 * A BLE_ERR_[...] error code on failure.
591 */
592 int
ble_hci_trans_ll_acl_tx(struct os_mbuf * om)593 ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
594 {
595 return ble_hci_sock_acl_tx(om);
596 }
597
598 /**
599 * Sends an HCI command from the host to the controller.
600 *
601 * @param cmd The HCI command to send. This buffer must be
602 * allocated via ble_hci_trans_buf_alloc().
603 *
604 * @return 0 on success;
605 * A BLE_ERR_[...] error code on failure.
606 */
607 int
ble_hci_trans_hs_cmd_tx(uint8_t * cmd)608 ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
609 {
610 return ble_hci_sock_cmdevt_tx(cmd, BLE_HCI_UART_H4_CMD);
611 }
612
613 /**
614 * Sends ACL data from host to controller.
615 *
616 * @param om The ACL data packet to send.
617 *
618 * @return 0 on success;
619 * A BLE_ERR_[...] error code on failure.
620 */
621 int
ble_hci_trans_hs_acl_tx(struct os_mbuf * om)622 ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
623 {
624 return ble_hci_sock_acl_tx(om);
625 }
626
627 /**
628 * Configures the HCI transport to call the specified callback upon receiving
629 * HCI packets from the controller. This function should only be called by by
630 * host.
631 *
632 * @param cmd_cb The callback to execute upon receiving an HCI
633 * event.
634 * @param cmd_arg Optional argument to pass to the command
635 * callback.
636 * @param acl_cb The callback to execute upon receiving ACL
637 * data.
638 * @param acl_arg Optional argument to pass to the ACL
639 * callback.
640 */
641 void
ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn * cmd_cb,void * cmd_arg,ble_hci_trans_rx_acl_fn * acl_cb,void * acl_arg)642 ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb,
643 void *cmd_arg,
644 ble_hci_trans_rx_acl_fn *acl_cb,
645 void *acl_arg)
646 {
647 ble_hci_sock_rx_cmd_cb = cmd_cb;
648 ble_hci_sock_rx_cmd_arg = cmd_arg;
649 ble_hci_sock_rx_acl_cb = acl_cb;
650 ble_hci_sock_rx_acl_arg = acl_arg;
651 }
652
653 /**
654 * Configures the HCI transport to operate with a host. The transport will
655 * execute specified callbacks upon receiving HCI packets from the controller.
656 *
657 * @param cmd_cb The callback to execute upon receiving an HCI
658 * event.
659 * @param cmd_arg Optional argument to pass to the command
660 * callback.
661 * @param acl_cb The callback to execute upon receiving ACL
662 * data.
663 * @param acl_arg Optional argument to pass to the ACL
664 * callback.
665 */
666 void
ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn * cmd_cb,void * cmd_arg,ble_hci_trans_rx_acl_fn * acl_cb,void * acl_arg)667 ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
668 void *cmd_arg,
669 ble_hci_trans_rx_acl_fn *acl_cb,
670 void *acl_arg)
671 {
672 ble_hci_sock_rx_cmd_cb = cmd_cb;
673 ble_hci_sock_rx_cmd_arg = cmd_arg;
674 ble_hci_sock_rx_acl_cb = acl_cb;
675 ble_hci_sock_rx_acl_arg = acl_arg;
676 }
677
678 /**
679 * Allocates a flat buffer of the specified type.
680 *
681 * @param type The type of buffer to allocate; one of the
682 * BLE_HCI_TRANS_BUF_[...] constants.
683 *
684 * @return The allocated buffer on success;
685 * NULL on buffer exhaustion.
686 */
687 uint8_t *
ble_hci_trans_buf_alloc(int type)688 ble_hci_trans_buf_alloc(int type)
689 {
690 uint8_t *buf;
691
692 switch (type) {
693 case BLE_HCI_TRANS_BUF_CMD:
694 buf = os_memblock_get(&ble_hci_sock_cmd_pool);
695 break;
696 case BLE_HCI_TRANS_BUF_EVT_HI:
697 buf = os_memblock_get(&ble_hci_sock_evt_hi_pool);
698 if (buf == NULL) {
699 /* If no high-priority event buffers remain, try to grab a
700 * low-priority one.
701 */
702 buf = os_memblock_get(&ble_hci_sock_evt_lo_pool);
703 }
704 break;
705
706 case BLE_HCI_TRANS_BUF_EVT_LO:
707 buf = os_memblock_get(&ble_hci_sock_evt_lo_pool);
708 break;
709
710 default:
711 assert(0);
712 buf = NULL;
713 }
714
715 return buf;
716 }
717
718 /**
719 * Frees the specified flat buffer. The buffer must have been allocated via
720 * ble_hci_trans_buf_alloc().
721 *
722 * @param buf The buffer to free.
723 */
724 void
ble_hci_trans_buf_free(uint8_t * buf)725 ble_hci_trans_buf_free(uint8_t *buf)
726 {
727 int rc;
728
729 /*
730 * XXX: this may look a bit odd, but the controller uses the command
731 * buffer to send back the command complete/status as an immediate
732 * response to the command. This was done to insure that the controller
733 * could always send back one of these events when a command was received.
734 * Thus, we check to see which pool the buffer came from so we can free
735 * it to the appropriate pool
736 */
737 if (os_memblock_from(&ble_hci_sock_evt_hi_pool, buf)) {
738 rc = os_memblock_put(&ble_hci_sock_evt_hi_pool, buf);
739 assert(rc == 0);
740 } else if (os_memblock_from(&ble_hci_sock_evt_lo_pool, buf)) {
741 rc = os_memblock_put(&ble_hci_sock_evt_lo_pool, buf);
742 assert(rc == 0);
743 } else {
744 assert(os_memblock_from(&ble_hci_sock_cmd_pool, buf));
745 rc = os_memblock_put(&ble_hci_sock_cmd_pool, buf);
746 assert(rc == 0);
747 }
748 }
749
750 /**
751 * Resets the HCI UART transport to a clean state. Frees all buffers and
752 * reconfigures the UART.
753 *
754 * @return 0 on success;
755 * A BLE_ERR_[...] error code on failure.
756 */
757 int
ble_hci_trans_reset(void)758 ble_hci_trans_reset(void)
759 {
760 int rc;
761
762 ble_npl_callout_stop(&ble_hci_sock_state.timer);
763
764 /* Reopen the UART. */
765 rc = ble_hci_sock_config();
766 if (rc != 0) {
767 dprintf(1, "Failure restarting socket HCI\n");
768 return rc;
769 }
770
771 return 0;
772 }
773
774 void
ble_hci_sock_ack_handler(void * arg)775 ble_hci_sock_ack_handler(void *arg)
776 {
777 struct ble_npl_event *ev;
778
779 while (1) {
780 ev = ble_npl_eventq_get(&ble_hci_sock_state.evq, BLE_NPL_TIME_FOREVER);
781 ble_npl_event_run(ev);
782 }
783 }
784
785 static void
ble_hci_sock_init_task(void)786 ble_hci_sock_init_task(void)
787 {
788 ble_npl_eventq_init(&ble_hci_sock_state.evq);
789 ble_npl_callout_stop(&ble_hci_sock_state.timer);
790 ble_npl_callout_init(&ble_hci_sock_state.timer, &ble_hci_sock_state.evq,
791 ble_hci_sock_rx_ev, NULL);
792
793 #if MYNEWT
794 {
795 os_stack_t *pstack;
796
797 pstack = malloc(sizeof(os_stack_t)*BLE_SOCK_STACK_SIZE);
798 assert(pstack);
799 os_task_init(&ble_sock_task, "hci_sock", ble_hci_sock_ack_handler, NULL,
800 MYNEWT_VAL(BLE_SOCK_TASK_PRIO), BLE_NPL_TIME_FOREVER, pstack,
801 BLE_SOCK_STACK_SIZE);
802 }
803 #else
804 /*
805 * For non-Mynewt OS it is required that OS creates task for HCI SOCKET
806 * to run ble_hci_sock_ack_handler.
807 */
808
809 #endif
810
811 }
812
813 void
ble_hci_sock_set_device(int dev)814 ble_hci_sock_set_device(int dev)
815 {
816 s_ble_hci_device = dev;
817 }
818
819 /**
820 * Initializes the UART HCI transport module.
821 *
822 * @return 0 on success;
823 * A BLE_ERR_[...] error code on failure.
824 */
825 void
ble_hci_sock_init(void)826 ble_hci_sock_init(void)
827 {
828 int rc;
829
830 /* Ensure this function only gets called by sysinit. */
831 SYSINIT_ASSERT_ACTIVE();
832
833 memset(&ble_hci_sock_state, 0, sizeof(ble_hci_sock_state));
834 ble_hci_sock_state.sock = -1;
835
836 ble_hci_sock_init_task();
837 ble_npl_event_init(&ble_hci_sock_state.ev, ble_hci_sock_rx_ev, NULL);
838
839 rc = os_mempool_init(&ble_hci_sock_acl_pool,
840 MYNEWT_VAL(BLE_ACL_BUF_COUNT),
841 ACL_BLOCK_SIZE,
842 ble_hci_sock_acl_buf,
843 "ble_hci_sock_acl_pool");
844 SYSINIT_PANIC_ASSERT(rc == 0);
845
846 rc = os_mbuf_pool_init(&ble_hci_sock_acl_mbuf_pool,
847 &ble_hci_sock_acl_pool,
848 ACL_BLOCK_SIZE,
849 MYNEWT_VAL(BLE_ACL_BUF_COUNT));
850 SYSINIT_PANIC_ASSERT(rc == 0);
851
852 /*
853 * Create memory pool of HCI command buffers. NOTE: we currently dont
854 * allow this to be configured. The controller will only allow one
855 * outstanding command. We decided to keep this a pool in case we allow
856 * allow the controller to handle more than one outstanding command.
857 */
858 rc = os_mempool_init(&ble_hci_sock_cmd_pool,
859 1,
860 BLE_HCI_TRANS_CMD_SZ,
861 &ble_hci_sock_cmd_buf,
862 "ble_hci_sock_cmd_pool");
863 SYSINIT_PANIC_ASSERT(rc == 0);
864
865 rc = os_mempool_init(&ble_hci_sock_evt_hi_pool,
866 MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
867 MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
868 &ble_hci_sock_evt_hi_buf,
869 "ble_hci_sock_evt_hi_pool");
870 SYSINIT_PANIC_ASSERT(rc == 0);
871
872 rc = os_mempool_init(&ble_hci_sock_evt_lo_pool,
873 MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
874 MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
875 ble_hci_sock_evt_lo_buf,
876 "ble_hci_sock_evt_lo_pool");
877 SYSINIT_PANIC_ASSERT(rc == 0);
878
879 rc = ble_hci_sock_config();
880 SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failure configuring socket HCI");
881
882 rc = stats_init_and_reg(STATS_HDR(hci_sock_stats),
883 STATS_SIZE_INIT_PARMS(hci_sock_stats, STATS_SIZE_32),
884 STATS_NAME_INIT_PARMS(hci_sock_stats), "hci_socket");
885 SYSINIT_PANIC_ASSERT(rc == 0);
886 }
887