xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_hs_hci_util.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1*042d53a7SEvalZero /*
2*042d53a7SEvalZero  * Licensed to the Apache Software Foundation (ASF) under one
3*042d53a7SEvalZero  * or more contributor license agreements.  See the NOTICE file
4*042d53a7SEvalZero  * distributed with this work for additional information
5*042d53a7SEvalZero  * regarding copyright ownership.  The ASF licenses this file
6*042d53a7SEvalZero  * to you under the Apache License, Version 2.0 (the
7*042d53a7SEvalZero  * "License"); you may not use this file except in compliance
8*042d53a7SEvalZero  * with the License.  You may obtain a copy of the License at
9*042d53a7SEvalZero  *
10*042d53a7SEvalZero  *  http://www.apache.org/licenses/LICENSE-2.0
11*042d53a7SEvalZero  *
12*042d53a7SEvalZero  * Unless required by applicable law or agreed to in writing,
13*042d53a7SEvalZero  * software distributed under the License is distributed on an
14*042d53a7SEvalZero  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*042d53a7SEvalZero  * KIND, either express or implied.  See the License for the
16*042d53a7SEvalZero  * specific language governing permissions and limitations
17*042d53a7SEvalZero  * under the License.
18*042d53a7SEvalZero  */
19*042d53a7SEvalZero 
20*042d53a7SEvalZero #include <string.h>
21*042d53a7SEvalZero #include "nimble/hci_common.h"
22*042d53a7SEvalZero #include "host/ble_hs_hci.h"
23*042d53a7SEvalZero #include "ble_hs_priv.h"
24*042d53a7SEvalZero 
25*042d53a7SEvalZero uint16_t
ble_hs_hci_util_handle_pb_bc_join(uint16_t handle,uint8_t pb,uint8_t bc)26*042d53a7SEvalZero ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, uint8_t bc)
27*042d53a7SEvalZero {
28*042d53a7SEvalZero     BLE_HS_DBG_ASSERT(handle <= 0x0fff);
29*042d53a7SEvalZero     BLE_HS_DBG_ASSERT(pb <= 0x03);
30*042d53a7SEvalZero     BLE_HS_DBG_ASSERT(bc <= 0x03);
31*042d53a7SEvalZero 
32*042d53a7SEvalZero     return (handle  << 0)   |
33*042d53a7SEvalZero            (pb      << 12)  |
34*042d53a7SEvalZero            (bc      << 14);
35*042d53a7SEvalZero }
36*042d53a7SEvalZero 
37*042d53a7SEvalZero int
ble_hs_hci_util_read_adv_tx_pwr(int8_t * out_tx_pwr)38*042d53a7SEvalZero ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_tx_pwr)
39*042d53a7SEvalZero {
40*042d53a7SEvalZero     uint8_t params_len;
41*042d53a7SEvalZero     int rc;
42*042d53a7SEvalZero 
43*042d53a7SEvalZero     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
44*042d53a7SEvalZero                                       BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR),
45*042d53a7SEvalZero                            NULL, 0,out_tx_pwr, 1, &params_len);
46*042d53a7SEvalZero     if (rc != 0) {
47*042d53a7SEvalZero         return rc;
48*042d53a7SEvalZero     }
49*042d53a7SEvalZero 
50*042d53a7SEvalZero     if (params_len != 1                     ||
51*042d53a7SEvalZero         *out_tx_pwr < BLE_HCI_ADV_CHAN_TXPWR_MIN ||
52*042d53a7SEvalZero         *out_tx_pwr > BLE_HCI_ADV_CHAN_TXPWR_MAX) {
53*042d53a7SEvalZero         BLE_HS_LOG(WARN, "advertiser txpwr out of range\n");
54*042d53a7SEvalZero     }
55*042d53a7SEvalZero 
56*042d53a7SEvalZero     return 0;
57*042d53a7SEvalZero }
58*042d53a7SEvalZero 
59*042d53a7SEvalZero int
ble_hs_hci_util_rand(void * dst,int len)60*042d53a7SEvalZero ble_hs_hci_util_rand(void *dst, int len)
61*042d53a7SEvalZero {
62*042d53a7SEvalZero     uint8_t rsp_buf[BLE_HCI_LE_RAND_LEN];
63*042d53a7SEvalZero     uint8_t params_len;
64*042d53a7SEvalZero     uint8_t *u8ptr;
65*042d53a7SEvalZero     int chunk_sz;
66*042d53a7SEvalZero     int rc;
67*042d53a7SEvalZero 
68*042d53a7SEvalZero     u8ptr = dst;
69*042d53a7SEvalZero     while (len > 0) {
70*042d53a7SEvalZero         rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RAND),
71*042d53a7SEvalZero                                NULL, 0, rsp_buf, sizeof rsp_buf, &params_len);
72*042d53a7SEvalZero         if (rc != 0) {
73*042d53a7SEvalZero             return rc;
74*042d53a7SEvalZero         }
75*042d53a7SEvalZero         if (params_len != sizeof rsp_buf) {
76*042d53a7SEvalZero             return BLE_HS_ECONTROLLER;
77*042d53a7SEvalZero         }
78*042d53a7SEvalZero 
79*042d53a7SEvalZero         chunk_sz = min(len, sizeof rsp_buf);
80*042d53a7SEvalZero         memcpy(u8ptr, rsp_buf, chunk_sz);
81*042d53a7SEvalZero 
82*042d53a7SEvalZero         len -= chunk_sz;
83*042d53a7SEvalZero         u8ptr += chunk_sz;
84*042d53a7SEvalZero     }
85*042d53a7SEvalZero 
86*042d53a7SEvalZero     return 0;
87*042d53a7SEvalZero }
88*042d53a7SEvalZero 
89*042d53a7SEvalZero int
ble_hs_hci_util_read_rssi(uint16_t conn_handle,int8_t * out_rssi)90*042d53a7SEvalZero ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi)
91*042d53a7SEvalZero {
92*042d53a7SEvalZero     uint8_t buf[BLE_HCI_READ_RSSI_LEN];
93*042d53a7SEvalZero     uint8_t params[BLE_HCI_READ_RSSI_ACK_PARAM_LEN];
94*042d53a7SEvalZero     uint16_t params_conn_handle;
95*042d53a7SEvalZero     uint8_t params_len;
96*042d53a7SEvalZero     int rc;
97*042d53a7SEvalZero 
98*042d53a7SEvalZero     ble_hs_hci_cmd_build_read_rssi(conn_handle, buf, sizeof buf);
99*042d53a7SEvalZero     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_STATUS_PARAMS,
100*042d53a7SEvalZero                                       BLE_HCI_OCF_RD_RSSI), buf, sizeof(buf),
101*042d53a7SEvalZero                            params, sizeof(params), &params_len);
102*042d53a7SEvalZero     if (rc != 0) {
103*042d53a7SEvalZero         return rc;
104*042d53a7SEvalZero     }
105*042d53a7SEvalZero 
106*042d53a7SEvalZero     if (params_len != BLE_HCI_READ_RSSI_ACK_PARAM_LEN) {
107*042d53a7SEvalZero         return BLE_HS_ECONTROLLER;
108*042d53a7SEvalZero     }
109*042d53a7SEvalZero 
110*042d53a7SEvalZero     params_conn_handle = get_le16(params + 0);
111*042d53a7SEvalZero     if (params_conn_handle != conn_handle) {
112*042d53a7SEvalZero         return BLE_HS_ECONTROLLER;
113*042d53a7SEvalZero     }
114*042d53a7SEvalZero 
115*042d53a7SEvalZero     *out_rssi = params[2];
116*042d53a7SEvalZero 
117*042d53a7SEvalZero     return 0;
118*042d53a7SEvalZero }
119*042d53a7SEvalZero 
120*042d53a7SEvalZero int
ble_hs_hci_util_set_random_addr(const uint8_t * addr)121*042d53a7SEvalZero ble_hs_hci_util_set_random_addr(const uint8_t *addr)
122*042d53a7SEvalZero {
123*042d53a7SEvalZero     uint8_t buf[BLE_HCI_SET_RAND_ADDR_LEN];
124*042d53a7SEvalZero     int rc;
125*042d53a7SEvalZero 
126*042d53a7SEvalZero     /* set the address in the controller */
127*042d53a7SEvalZero 
128*042d53a7SEvalZero     rc = ble_hs_hci_cmd_build_set_random_addr(addr, buf, sizeof(buf));
129*042d53a7SEvalZero     if (rc != 0) {
130*042d53a7SEvalZero         return rc;
131*042d53a7SEvalZero     }
132*042d53a7SEvalZero 
133*042d53a7SEvalZero     rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
134*042d53a7SEvalZero                                                 BLE_HCI_OCF_LE_SET_RAND_ADDR),
135*042d53a7SEvalZero                                      buf, BLE_HCI_SET_RAND_ADDR_LEN);
136*042d53a7SEvalZero     if (rc != 0) {
137*042d53a7SEvalZero         return rc;
138*042d53a7SEvalZero     }
139*042d53a7SEvalZero 
140*042d53a7SEvalZero     return 0;
141*042d53a7SEvalZero }
142*042d53a7SEvalZero 
143*042d53a7SEvalZero int
ble_hs_hci_util_set_data_len(uint16_t conn_handle,uint16_t tx_octets,uint16_t tx_time)144*042d53a7SEvalZero ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
145*042d53a7SEvalZero                              uint16_t tx_time)
146*042d53a7SEvalZero {
147*042d53a7SEvalZero 
148*042d53a7SEvalZero     uint8_t buf[BLE_HCI_SET_DATALEN_LEN];
149*042d53a7SEvalZero     uint8_t params[BLE_HCI_SET_DATALEN_ACK_PARAM_LEN];
150*042d53a7SEvalZero     uint16_t params_conn_handle;
151*042d53a7SEvalZero     uint8_t params_len;
152*042d53a7SEvalZero     int rc;
153*042d53a7SEvalZero 
154*042d53a7SEvalZero     rc = ble_hs_hci_cmd_build_set_data_len(conn_handle, tx_octets, tx_time,
155*042d53a7SEvalZero                                            buf, sizeof buf);
156*042d53a7SEvalZero     if (rc != 0) {
157*042d53a7SEvalZero         return BLE_HS_HCI_ERR(rc);
158*042d53a7SEvalZero     }
159*042d53a7SEvalZero 
160*042d53a7SEvalZero     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
161*042d53a7SEvalZero                                       BLE_HCI_OCF_LE_SET_DATA_LEN),
162*042d53a7SEvalZero                            buf, sizeof(buf), params,
163*042d53a7SEvalZero                            BLE_HCI_SET_DATALEN_ACK_PARAM_LEN, &params_len);
164*042d53a7SEvalZero     if (rc != 0) {
165*042d53a7SEvalZero         return rc;
166*042d53a7SEvalZero     }
167*042d53a7SEvalZero 
168*042d53a7SEvalZero     if (params_len != BLE_HCI_SET_DATALEN_ACK_PARAM_LEN) {
169*042d53a7SEvalZero         return BLE_HS_ECONTROLLER;
170*042d53a7SEvalZero     }
171*042d53a7SEvalZero 
172*042d53a7SEvalZero     params_conn_handle = get_le16(params + 0);
173*042d53a7SEvalZero     if (params_conn_handle != conn_handle) {
174*042d53a7SEvalZero         return BLE_HS_ECONTROLLER;
175*042d53a7SEvalZero     }
176*042d53a7SEvalZero 
177*042d53a7SEvalZero     return 0;
178*042d53a7SEvalZero }
179*042d53a7SEvalZero 
180*042d53a7SEvalZero int
ble_hs_hci_util_data_hdr_strip(struct os_mbuf * om,struct hci_data_hdr * out_hdr)181*042d53a7SEvalZero ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om,
182*042d53a7SEvalZero                                struct hci_data_hdr *out_hdr)
183*042d53a7SEvalZero {
184*042d53a7SEvalZero     int rc;
185*042d53a7SEvalZero 
186*042d53a7SEvalZero     rc = os_mbuf_copydata(om, 0, BLE_HCI_DATA_HDR_SZ, out_hdr);
187*042d53a7SEvalZero     if (rc != 0) {
188*042d53a7SEvalZero         return BLE_HS_ECONTROLLER;
189*042d53a7SEvalZero     }
190*042d53a7SEvalZero 
191*042d53a7SEvalZero     /* Strip HCI ACL data header from the front of the packet. */
192*042d53a7SEvalZero     os_mbuf_adj(om, BLE_HCI_DATA_HDR_SZ);
193*042d53a7SEvalZero 
194*042d53a7SEvalZero     out_hdr->hdh_handle_pb_bc = get_le16(&out_hdr->hdh_handle_pb_bc);
195*042d53a7SEvalZero     out_hdr->hdh_len = get_le16(&out_hdr->hdh_len);
196*042d53a7SEvalZero 
197*042d53a7SEvalZero     return 0;
198*042d53a7SEvalZero }
199*042d53a7SEvalZero 
200*042d53a7SEvalZero int
ble_hs_hci_read_chan_map(uint16_t conn_handle,uint8_t * out_chan_map)201*042d53a7SEvalZero ble_hs_hci_read_chan_map(uint16_t conn_handle, uint8_t *out_chan_map)
202*042d53a7SEvalZero {
203*042d53a7SEvalZero     uint8_t buf[BLE_HCI_RD_CHANMAP_LEN];
204*042d53a7SEvalZero     uint8_t params[BLE_HCI_RD_CHANMAP_RSP_LEN];
205*042d53a7SEvalZero     uint16_t params_conn_handle;
206*042d53a7SEvalZero     uint8_t params_len;
207*042d53a7SEvalZero     int rc;
208*042d53a7SEvalZero 
209*042d53a7SEvalZero     ble_hs_hci_cmd_build_le_read_chan_map(conn_handle, buf, sizeof buf);
210*042d53a7SEvalZero     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
211*042d53a7SEvalZero                                       BLE_HCI_OCF_LE_RD_CHAN_MAP),
212*042d53a7SEvalZero                            buf, sizeof(buf), params, BLE_HCI_RD_CHANMAP_RSP_LEN,
213*042d53a7SEvalZero                            &params_len);
214*042d53a7SEvalZero     if (rc != 0) {
215*042d53a7SEvalZero         return rc;
216*042d53a7SEvalZero     }
217*042d53a7SEvalZero 
218*042d53a7SEvalZero     if (params_len != BLE_HCI_RD_CHANMAP_RSP_LEN) {
219*042d53a7SEvalZero         return BLE_HS_ECONTROLLER;
220*042d53a7SEvalZero     }
221*042d53a7SEvalZero 
222*042d53a7SEvalZero     params_conn_handle = get_le16(params + 0);
223*042d53a7SEvalZero     if (params_conn_handle != conn_handle) {
224*042d53a7SEvalZero         return BLE_HS_ECONTROLLER;
225*042d53a7SEvalZero     }
226*042d53a7SEvalZero 
227*042d53a7SEvalZero     memcpy(out_chan_map, params + 2, 5);
228*042d53a7SEvalZero 
229*042d53a7SEvalZero     return 0;
230*042d53a7SEvalZero }
231*042d53a7SEvalZero 
232*042d53a7SEvalZero int
ble_hs_hci_set_chan_class(const uint8_t * chan_map)233*042d53a7SEvalZero ble_hs_hci_set_chan_class(const uint8_t *chan_map)
234*042d53a7SEvalZero {
235*042d53a7SEvalZero     uint8_t buf[BLE_HCI_SET_HOST_CHAN_CLASS_LEN];
236*042d53a7SEvalZero     int rc;
237*042d53a7SEvalZero 
238*042d53a7SEvalZero     ble_hs_hci_cmd_build_le_set_host_chan_class(chan_map, buf, sizeof buf);
239*042d53a7SEvalZero     rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
240*042d53a7SEvalZero                                             BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS),
241*042d53a7SEvalZero                                      buf, sizeof(buf));
242*042d53a7SEvalZero     if (rc != 0) {
243*042d53a7SEvalZero         return rc;
244*042d53a7SEvalZero     }
245*042d53a7SEvalZero 
246*042d53a7SEvalZero     return 0;
247*042d53a7SEvalZero }
248