xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/transport/socket/src/ble_hci_socket.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 
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