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 "securec.h"
22 #include "nimble/hci_common.h"
23 #include "host/ble_hs_hci.h"
24 #include "ble_hs_priv.h"
25
ble_hs_hci_util_handle_pb_bc_join(uint16_t handle,uint8_t pb,uint8_t bc)26 uint16_t 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 return (handle << 0) |
32 (pb << 12) | // 12:byte alignment
33 (bc << 14); // 14:byte alignment
34 }
35
ble_hs_hci_util_read_adv_tx_pwr(int8_t * out_tx_pwr)36 int ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_tx_pwr)
37 {
38 struct ble_hci_le_rd_adv_chan_txpwr_rp rsp;
39 int rc;
40 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
41 BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR),
42 NULL, 0, &rsp, sizeof(rsp));
43 if (rc != 0) {
44 return rc;
45 }
46
47 *out_tx_pwr = rsp.power_level;
48 if (*out_tx_pwr < BLE_HCI_ADV_CHAN_TXPWR_MIN ||
49 *out_tx_pwr > BLE_HCI_ADV_CHAN_TXPWR_MAX) {
50 BLE_HS_LOG(WARN, "advertiser txpwr out of range\n");
51 }
52
53 return 0;
54 }
55
ble_hs_hci_util_rand(void * dst,int len)56 int ble_hs_hci_util_rand(void *dst, int len)
57 {
58 int len_tmp = len;
59 struct ble_hci_le_rand_rp rsp;
60 uint8_t *u8ptr;
61
62 u8ptr = dst;
63
64 while (len_tmp > 0) {
65 int rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RAND), NULL, 0, &rsp, sizeof(rsp));
66 if (rc != 0) {
67 return rc;
68 }
69
70 int chunk_sz = min(len_tmp, sizeof(rsp));
71 memcpy_s(u8ptr, sizeof(u8ptr), &rsp.random_number, chunk_sz);
72 len_tmp -= chunk_sz;
73 u8ptr += chunk_sz;
74 }
75
76 return 0;
77 }
78
ble_hs_hci_util_read_rssi(uint16_t conn_handle,int8_t * out_rssi)79 int ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi)
80 {
81 struct ble_hci_rd_rssi_cp cmd;
82 struct ble_hci_rd_rssi_rp rsp;
83 int rc;
84 cmd.handle = htole16(conn_handle);
85 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_STATUS_PARAMS, BLE_HCI_OCF_RD_RSSI), &cmd, sizeof(cmd),
86 &rsp, sizeof(rsp));
87 if (rc != 0) {
88 return rc;
89 }
90
91 if (le16toh(rsp.handle) != conn_handle) {
92 return BLE_HS_ECONTROLLER;
93 }
94
95 *out_rssi = rsp.rssi;
96 return 0;
97 }
98
ble_hs_hci_util_set_random_addr(const uint8_t * addr)99 int ble_hs_hci_util_set_random_addr(const uint8_t *addr)
100 {
101 struct ble_hci_le_set_rand_addr_cp cmd;
102 memcpy_s(cmd.addr, sizeof(cmd.addr), addr, BLE_DEV_ADDR_LEN);
103 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
104 BLE_HCI_OCF_LE_SET_RAND_ADDR),
105 &cmd, sizeof(cmd), NULL, 0);
106 }
107
ble_hs_hci_util_set_data_len(uint16_t conn_handle,uint16_t tx_octets,uint16_t tx_time)108 int ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time)
109 {
110 struct ble_hci_le_set_data_len_cp cmd;
111 struct ble_hci_le_set_data_len_rp rsp;
112 int rc;
113
114 if (tx_octets < BLE_HCI_SET_DATALEN_TX_OCTETS_MIN ||
115 tx_octets > BLE_HCI_SET_DATALEN_TX_OCTETS_MAX) {
116 return BLE_HS_EINVAL;
117 }
118
119 if (tx_time < BLE_HCI_SET_DATALEN_TX_TIME_MIN ||
120 tx_time > BLE_HCI_SET_DATALEN_TX_TIME_MAX) {
121 return BLE_HS_EINVAL;
122 }
123
124 cmd.conn_handle = htole16(conn_handle);
125 cmd.tx_octets = htole16(tx_octets);
126 cmd.tx_time = htole16(tx_time);
127 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
128 BLE_HCI_OCF_LE_SET_DATA_LEN),
129 &cmd, sizeof(cmd), NULL, 0);
130 if (rc != 0) {
131 return rc;
132 }
133
134 if (le16toh(rsp.conn_handle) != conn_handle) {
135 return BLE_HS_ECONTROLLER;
136 }
137
138 return 0;
139 }
140
ble_hs_hci_util_data_hdr_strip(struct os_mbuf * om,struct hci_data_hdr * out_hdr)141 int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om, struct hci_data_hdr *out_hdr)
142 {
143 int rc;
144 rc = os_mbuf_copydata(om, 0, BLE_HCI_DATA_HDR_SZ, out_hdr);
145 if (rc != 0) {
146 return BLE_HS_ECONTROLLER;
147 }
148
149 /* Strip HCI ACL data header from the front of the packet. */
150 os_mbuf_adj(om, BLE_HCI_DATA_HDR_SZ);
151 out_hdr->hdh_handle_pb_bc = get_le16(&out_hdr->hdh_handle_pb_bc);
152 out_hdr->hdh_len = get_le16(&out_hdr->hdh_len);
153 return 0;
154 }
155
ble_hs_hci_read_chan_map(uint16_t conn_handle,uint8_t * out_chan_map)156 int ble_hs_hci_read_chan_map(uint16_t conn_handle, uint8_t *out_chan_map)
157 {
158 struct ble_hci_le_rd_chan_map_cp cmd;
159 struct ble_hci_le_rd_chan_map_rp rsp;
160 int rc;
161 cmd.conn_handle = htole16(conn_handle);
162 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
163 BLE_HCI_OCF_LE_RD_CHAN_MAP),
164 &cmd, sizeof(cmd), &rsp, sizeof(rsp));
165 if (rc != 0) {
166 return rc;
167 }
168
169 if (le16toh(rsp.conn_handle) != conn_handle) {
170 return BLE_HS_ECONTROLLER;
171 }
172
173 memcpy_s(out_chan_map, sizeof(out_chan_map), rsp.chan_map, 5); // 5:size
174 return 0;
175 }
176
ble_hs_hci_set_chan_class(const uint8_t * chan_map)177 int ble_hs_hci_set_chan_class(const uint8_t *chan_map)
178 {
179 struct ble_hci_le_set_host_chan_class_cp cmd;
180 memcpy_s(cmd.chan_map, sizeof(cmd.chan_map), chan_map, sizeof(cmd.chan_map));
181 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
182 BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS),
183 &cmd, sizeof(cmd), NULL, 0);
184 }