xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/transport/ram/src/ble_hci_ram.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 #include <assert.h>
21 #include <errno.h>
22 #include <stddef.h>
23 #include "syscfg/syscfg.h"
24 #include "sysinit/sysinit.h"
25 #include "os/os.h"
26 #include "mem/mem.h"
27 #include "nimble/ble.h"
28 #include "nimble/ble_hci_trans.h"
29 #include "transport/ram/ble_hci_ram.h"
30 
31 static ble_hci_trans_rx_cmd_fn *ble_hci_ram_rx_cmd_hs_cb;
32 static void *ble_hci_ram_rx_cmd_hs_arg;
33 
34 static ble_hci_trans_rx_cmd_fn *ble_hci_ram_rx_cmd_ll_cb;
35 static void *ble_hci_ram_rx_cmd_ll_arg;
36 
37 static ble_hci_trans_rx_acl_fn *ble_hci_ram_rx_acl_hs_cb;
38 static void *ble_hci_ram_rx_acl_hs_arg;
39 
40 static ble_hci_trans_rx_acl_fn *ble_hci_ram_rx_acl_ll_cb;
41 static void *ble_hci_ram_rx_acl_ll_arg;
42 
43 static struct os_mempool ble_hci_ram_cmd_pool;
44 static os_membuf_t ble_hci_ram_cmd_buf[
45         OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ)
46 ];
47 
48 static struct os_mempool ble_hci_ram_evt_hi_pool;
49 static os_membuf_t ble_hci_ram_evt_hi_buf[
50     OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
51                     MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
52 ];
53 
54 static struct os_mempool ble_hci_ram_evt_lo_pool;
55 static os_membuf_t ble_hci_ram_evt_lo_buf[
56         OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
57                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
58 ];
59 
60 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)61 ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb,
62                      void *cmd_arg,
63                      ble_hci_trans_rx_acl_fn *acl_cb,
64                      void *acl_arg)
65 {
66     ble_hci_ram_rx_cmd_hs_cb = cmd_cb;
67     ble_hci_ram_rx_cmd_hs_arg = cmd_arg;
68     ble_hci_ram_rx_acl_hs_cb = acl_cb;
69     ble_hci_ram_rx_acl_hs_arg = acl_arg;
70 }
71 
72 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)73 ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
74                      void *cmd_arg,
75                      ble_hci_trans_rx_acl_fn *acl_cb,
76                      void *acl_arg)
77 {
78     ble_hci_ram_rx_cmd_ll_cb = cmd_cb;
79     ble_hci_ram_rx_cmd_ll_arg = cmd_arg;
80     ble_hci_ram_rx_acl_ll_cb = acl_cb;
81     ble_hci_ram_rx_acl_ll_arg = acl_arg;
82 }
83 
84 int
ble_hci_trans_hs_cmd_tx(uint8_t * cmd)85 ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
86 {
87     int rc;
88 
89     assert(ble_hci_ram_rx_cmd_ll_cb != NULL);
90 
91     rc = ble_hci_ram_rx_cmd_ll_cb(cmd, ble_hci_ram_rx_cmd_ll_arg);
92     return rc;
93 }
94 
95 int
ble_hci_trans_ll_evt_tx(uint8_t * hci_ev)96 ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
97 {
98     int rc;
99 
100     assert(ble_hci_ram_rx_cmd_hs_cb != NULL);
101 
102     rc = ble_hci_ram_rx_cmd_hs_cb(hci_ev, ble_hci_ram_rx_cmd_hs_arg);
103     return rc;
104 }
105 
106 int
ble_hci_trans_hs_acl_tx(struct os_mbuf * om)107 ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
108 {
109     int rc;
110 
111     assert(ble_hci_ram_rx_acl_ll_cb != NULL);
112 
113     rc = ble_hci_ram_rx_acl_ll_cb(om, ble_hci_ram_rx_acl_ll_arg);
114     return rc;
115 }
116 
117 int
ble_hci_trans_ll_acl_tx(struct os_mbuf * om)118 ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
119 {
120     int rc;
121 
122     assert(ble_hci_ram_rx_acl_hs_cb != NULL);
123 
124     rc = ble_hci_ram_rx_acl_hs_cb(om, ble_hci_ram_rx_acl_hs_arg);
125     return rc;
126 }
127 
128 uint8_t *
ble_hci_trans_buf_alloc(int type)129 ble_hci_trans_buf_alloc(int type)
130 {
131     uint8_t *buf;
132 
133     switch (type) {
134     case BLE_HCI_TRANS_BUF_CMD:
135         buf = os_memblock_get(&ble_hci_ram_cmd_pool);
136         break;
137 
138     case BLE_HCI_TRANS_BUF_EVT_HI:
139         buf = os_memblock_get(&ble_hci_ram_evt_hi_pool);
140         if (buf == NULL) {
141             /* If no high-priority event buffers remain, try to grab a
142              * low-priority one.
143              */
144             buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
145         }
146         break;
147 
148     case BLE_HCI_TRANS_BUF_EVT_LO:
149         buf = os_memblock_get(&ble_hci_ram_evt_lo_pool);
150         break;
151 
152     default:
153         assert(0);
154         buf = NULL;
155     }
156 
157     return buf;
158 }
159 
160 void
ble_hci_trans_buf_free(uint8_t * buf)161 ble_hci_trans_buf_free(uint8_t *buf)
162 {
163     int rc;
164 
165     /* XXX: this may look a bit odd, but the controller uses the command
166     * buffer to send back the command complete/status as an immediate
167     * response to the command. This was done to insure that the controller
168     * could always send back one of these events when a command was received.
169     * Thus, we check to see which pool the buffer came from so we can free
170     * it to the appropriate pool
171     */
172     if (os_memblock_from(&ble_hci_ram_evt_hi_pool, buf)) {
173         rc = os_memblock_put(&ble_hci_ram_evt_hi_pool, buf);
174         assert(rc == 0);
175     } else if (os_memblock_from(&ble_hci_ram_evt_lo_pool, buf)) {
176         rc = os_memblock_put(&ble_hci_ram_evt_lo_pool, buf);
177         assert(rc == 0);
178     } else {
179         assert(os_memblock_from(&ble_hci_ram_cmd_pool, buf));
180         rc = os_memblock_put(&ble_hci_ram_cmd_pool, buf);
181         assert(rc == 0);
182     }
183 }
184 
185 /**
186  * Unsupported; the RAM transport does not have a dedicated ACL data packet
187  * pool.
188  */
189 int
ble_hci_trans_set_acl_free_cb(os_mempool_put_fn * cb,void * arg)190 ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg)
191 {
192     return BLE_ERR_UNSUPPORTED;
193 }
194 
195 int
ble_hci_trans_reset(void)196 ble_hci_trans_reset(void)
197 {
198     /* No work to do.  All allocated buffers are owned by the host or
199      * controller, and they will get freed by their owners.
200      */
201     return 0;
202 }
203 
204 void
ble_hci_ram_init(void)205 ble_hci_ram_init(void)
206 {
207     int rc;
208 
209     /* Ensure this function only gets called by sysinit. */
210     SYSINIT_ASSERT_ACTIVE();
211 
212     /*
213      * Create memory pool of HCI command buffers. NOTE: we currently dont
214      * allow this to be configured. The controller will only allow one
215      * outstanding command. We decided to keep this a pool in case we allow
216      * allow the controller to handle more than one outstanding command.
217      */
218     rc = os_mempool_init(&ble_hci_ram_cmd_pool,
219                          1,
220                          BLE_HCI_TRANS_CMD_SZ,
221                          ble_hci_ram_cmd_buf,
222                          "ble_hci_ram_cmd_pool");
223     SYSINIT_PANIC_ASSERT(rc == 0);
224 
225     rc = os_mempool_init(&ble_hci_ram_evt_hi_pool,
226                          MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
227                          MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
228                          ble_hci_ram_evt_hi_buf,
229                          "ble_hci_ram_evt_hi_pool");
230     SYSINIT_PANIC_ASSERT(rc == 0);
231 
232     rc = os_mempool_init(&ble_hci_ram_evt_lo_pool,
233                          MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
234                          MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
235                          ble_hci_ram_evt_lo_buf,
236                          "ble_hci_ram_evt_lo_pool");
237     SYSINIT_PANIC_ASSERT(rc == 0);
238 }
239