xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_hs_hci_util.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 <string.h>
21 #include "nimble/hci_common.h"
22 #include "host/ble_hs_hci.h"
23 #include "ble_hs_priv.h"
24 
25 uint16_t
ble_hs_hci_util_handle_pb_bc_join(uint16_t handle,uint8_t pb,uint8_t bc)26 ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, uint8_t bc)
27 {
28     BLE_HS_DBG_ASSERT(handle <= 0x0fff);
29     BLE_HS_DBG_ASSERT(pb <= 0x03);
30     BLE_HS_DBG_ASSERT(bc <= 0x03);
31 
32     return (handle  << 0)   |
33            (pb      << 12)  |
34            (bc      << 14);
35 }
36 
37 int
ble_hs_hci_util_read_adv_tx_pwr(int8_t * out_tx_pwr)38 ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_tx_pwr)
39 {
40     uint8_t params_len;
41     int rc;
42 
43     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
44                                       BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR),
45                            NULL, 0,out_tx_pwr, 1, &params_len);
46     if (rc != 0) {
47         return rc;
48     }
49 
50     if (params_len != 1                     ||
51         *out_tx_pwr < BLE_HCI_ADV_CHAN_TXPWR_MIN ||
52         *out_tx_pwr > BLE_HCI_ADV_CHAN_TXPWR_MAX) {
53         BLE_HS_LOG(WARN, "advertiser txpwr out of range\n");
54     }
55 
56     return 0;
57 }
58 
59 int
ble_hs_hci_util_rand(void * dst,int len)60 ble_hs_hci_util_rand(void *dst, int len)
61 {
62     uint8_t rsp_buf[BLE_HCI_LE_RAND_LEN];
63     uint8_t params_len;
64     uint8_t *u8ptr;
65     int chunk_sz;
66     int rc;
67 
68     u8ptr = dst;
69     while (len > 0) {
70         rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RAND),
71                                NULL, 0, rsp_buf, sizeof rsp_buf, &params_len);
72         if (rc != 0) {
73             return rc;
74         }
75         if (params_len != sizeof rsp_buf) {
76             return BLE_HS_ECONTROLLER;
77         }
78 
79         chunk_sz = min(len, sizeof rsp_buf);
80         memcpy(u8ptr, rsp_buf, chunk_sz);
81 
82         len -= chunk_sz;
83         u8ptr += chunk_sz;
84     }
85 
86     return 0;
87 }
88 
89 int
ble_hs_hci_util_read_rssi(uint16_t conn_handle,int8_t * out_rssi)90 ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi)
91 {
92     uint8_t buf[BLE_HCI_READ_RSSI_LEN];
93     uint8_t params[BLE_HCI_READ_RSSI_ACK_PARAM_LEN];
94     uint16_t params_conn_handle;
95     uint8_t params_len;
96     int rc;
97 
98     ble_hs_hci_cmd_build_read_rssi(conn_handle, buf, sizeof buf);
99     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_STATUS_PARAMS,
100                                       BLE_HCI_OCF_RD_RSSI), buf, sizeof(buf),
101                            params, sizeof(params), &params_len);
102     if (rc != 0) {
103         return rc;
104     }
105 
106     if (params_len != BLE_HCI_READ_RSSI_ACK_PARAM_LEN) {
107         return BLE_HS_ECONTROLLER;
108     }
109 
110     params_conn_handle = get_le16(params + 0);
111     if (params_conn_handle != conn_handle) {
112         return BLE_HS_ECONTROLLER;
113     }
114 
115     *out_rssi = params[2];
116 
117     return 0;
118 }
119 
120 int
ble_hs_hci_util_set_random_addr(const uint8_t * addr)121 ble_hs_hci_util_set_random_addr(const uint8_t *addr)
122 {
123     uint8_t buf[BLE_HCI_SET_RAND_ADDR_LEN];
124     int rc;
125 
126     /* set the address in the controller */
127 
128     rc = ble_hs_hci_cmd_build_set_random_addr(addr, buf, sizeof(buf));
129     if (rc != 0) {
130         return rc;
131     }
132 
133     rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
134                                                 BLE_HCI_OCF_LE_SET_RAND_ADDR),
135                                      buf, BLE_HCI_SET_RAND_ADDR_LEN);
136     if (rc != 0) {
137         return rc;
138     }
139 
140     return 0;
141 }
142 
143 int
ble_hs_hci_util_set_data_len(uint16_t conn_handle,uint16_t tx_octets,uint16_t tx_time)144 ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
145                              uint16_t tx_time)
146 {
147 
148     uint8_t buf[BLE_HCI_SET_DATALEN_LEN];
149     uint8_t params[BLE_HCI_SET_DATALEN_ACK_PARAM_LEN];
150     uint16_t params_conn_handle;
151     uint8_t params_len;
152     int rc;
153 
154     rc = ble_hs_hci_cmd_build_set_data_len(conn_handle, tx_octets, tx_time,
155                                            buf, sizeof buf);
156     if (rc != 0) {
157         return BLE_HS_HCI_ERR(rc);
158     }
159 
160     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
161                                       BLE_HCI_OCF_LE_SET_DATA_LEN),
162                            buf, sizeof(buf), params,
163                            BLE_HCI_SET_DATALEN_ACK_PARAM_LEN, &params_len);
164     if (rc != 0) {
165         return rc;
166     }
167 
168     if (params_len != BLE_HCI_SET_DATALEN_ACK_PARAM_LEN) {
169         return BLE_HS_ECONTROLLER;
170     }
171 
172     params_conn_handle = get_le16(params + 0);
173     if (params_conn_handle != conn_handle) {
174         return BLE_HS_ECONTROLLER;
175     }
176 
177     return 0;
178 }
179 
180 int
ble_hs_hci_util_data_hdr_strip(struct os_mbuf * om,struct hci_data_hdr * out_hdr)181 ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om,
182                                struct hci_data_hdr *out_hdr)
183 {
184     int rc;
185 
186     rc = os_mbuf_copydata(om, 0, BLE_HCI_DATA_HDR_SZ, out_hdr);
187     if (rc != 0) {
188         return BLE_HS_ECONTROLLER;
189     }
190 
191     /* Strip HCI ACL data header from the front of the packet. */
192     os_mbuf_adj(om, BLE_HCI_DATA_HDR_SZ);
193 
194     out_hdr->hdh_handle_pb_bc = get_le16(&out_hdr->hdh_handle_pb_bc);
195     out_hdr->hdh_len = get_le16(&out_hdr->hdh_len);
196 
197     return 0;
198 }
199 
200 int
ble_hs_hci_read_chan_map(uint16_t conn_handle,uint8_t * out_chan_map)201 ble_hs_hci_read_chan_map(uint16_t conn_handle, uint8_t *out_chan_map)
202 {
203     uint8_t buf[BLE_HCI_RD_CHANMAP_LEN];
204     uint8_t params[BLE_HCI_RD_CHANMAP_RSP_LEN];
205     uint16_t params_conn_handle;
206     uint8_t params_len;
207     int rc;
208 
209     ble_hs_hci_cmd_build_le_read_chan_map(conn_handle, buf, sizeof buf);
210     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
211                                       BLE_HCI_OCF_LE_RD_CHAN_MAP),
212                            buf, sizeof(buf), params, BLE_HCI_RD_CHANMAP_RSP_LEN,
213                            &params_len);
214     if (rc != 0) {
215         return rc;
216     }
217 
218     if (params_len != BLE_HCI_RD_CHANMAP_RSP_LEN) {
219         return BLE_HS_ECONTROLLER;
220     }
221 
222     params_conn_handle = get_le16(params + 0);
223     if (params_conn_handle != conn_handle) {
224         return BLE_HS_ECONTROLLER;
225     }
226 
227     memcpy(out_chan_map, params + 2, 5);
228 
229     return 0;
230 }
231 
232 int
ble_hs_hci_set_chan_class(const uint8_t * chan_map)233 ble_hs_hci_set_chan_class(const uint8_t *chan_map)
234 {
235     uint8_t buf[BLE_HCI_SET_HOST_CHAN_CLASS_LEN];
236     int rc;
237 
238     ble_hs_hci_cmd_build_le_set_host_chan_class(chan_map, buf, sizeof buf);
239     rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
240                                             BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS),
241                                      buf, sizeof(buf));
242     if (rc != 0) {
243         return rc;
244     }
245 
246     return 0;
247 }
248