1 /*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "android.hardware.bluetooth.service.default"
18
19 #include "net_bluetooth_mgmt.h"
20
21 #include <fcntl.h>
22 #include <log/log.h>
23 #include <poll.h>
24 #include <sys/socket.h>
25 #include <unistd.h>
26
27 #include <cerrno>
28 #include <cstdint>
29 #include <cstdlib>
30 #include <cstring>
31
32 // Definitions imported from <linux/net/bluetooth/bluetooth.h>
33 #define BTPROTO_HCI 1
34
35 // Definitions imported from <linux/net/bluetooth/hci_sock.h>
36 #define HCI_CHANNEL_USER 1
37 #define HCI_CHANNEL_CONTROL 3
38 #define HCI_DEV_NONE 0xffff
39
40 struct sockaddr_hci {
41 sa_family_t hci_family;
42 unsigned short hci_dev;
43 unsigned short hci_channel;
44 };
45
46 // Definitions imported from <linux/net/bluetooth/mgmt.h>
47 #define MGMT_OP_READ_INDEX_LIST 0x0003
48 #define MGMT_EV_INDEX_ADDED 0x0004
49 #define MGMT_EV_CMD_COMPLETE 0x0001
50 #define MGMT_PKT_SIZE_MAX 1024
51 #define MGMT_INDEX_NONE 0xFFFF
52
53 struct mgmt_pkt {
54 uint16_t opcode;
55 uint16_t index;
56 uint16_t len;
57 uint8_t data[MGMT_PKT_SIZE_MAX];
58 } __attribute__((packed));
59
60 struct mgmt_ev_read_index_list {
61 uint16_t opcode;
62 uint8_t status;
63 uint16_t num_controllers;
64 uint16_t index[];
65 } __attribute__((packed));
66
67 // Definitions imported from <linux/rfkill.h>
68 #define RFKILL_STATE_SOFT_BLOCKED 0
69 #define RFKILL_STATE_UNBLOCKED 1
70 #define RFKILL_STATE_HARD_BLOCKED 2
71
72 #define RFKILL_TYPE_BLUETOOTH 2
73
74 #define RFKILL_OP_ADD 0
75 #define RFKILL_OP_CHANGE 2
76
77 struct rfkill_event {
78 uint32_t idx;
79 uint8_t type;
80 uint8_t op;
81 uint8_t soft;
82 uint8_t hard;
83 } __attribute__((packed));
84
85 namespace aidl::android::hardware::bluetooth::impl {
86
87 // Wait indefinitely for the selected HCI interface to be enabled in the
88 // bluetooth driver.
waitHciDev(int hci_interface)89 int NetBluetoothMgmt::waitHciDev(int hci_interface) {
90 ALOGI("waiting for hci interface %d", hci_interface);
91
92 int ret = -1;
93 struct mgmt_pkt cmd;
94 struct pollfd pollfd;
95 struct sockaddr_hci hci_addr = {
96 .hci_family = AF_BLUETOOTH,
97 .hci_dev = HCI_DEV_NONE,
98 .hci_channel = HCI_CHANNEL_CONTROL,
99 };
100
101 // Open and bind a socket to the bluetooth control interface in the
102 // kernel driver, used to send control commands and receive control
103 // events.
104 int fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
105 if (fd < 0) {
106 ALOGE("unable to open raw bluetooth socket: %s", strerror(errno));
107 return -1;
108 }
109
110 if (bind(fd, (struct sockaddr*)&hci_addr, sizeof(hci_addr)) < 0) {
111 ALOGE("unable to bind bluetooth control channel: %s", strerror(errno));
112 goto end;
113 }
114
115 // Send the control command [Read Index List].
116 cmd = {
117 .opcode = MGMT_OP_READ_INDEX_LIST,
118 .index = MGMT_INDEX_NONE,
119 .len = 0,
120 };
121
122 if (write(fd, &cmd, 6) != 6) {
123 ALOGE("error writing mgmt command: %s", strerror(errno));
124 goto end;
125 }
126
127 // Poll the control socket waiting for the command response,
128 // and subsequent [Index Added] events. The loops continue without
129 // timeout until the selected hci interface is detected.
130 pollfd = {.fd = fd, .events = POLLIN};
131
132 for (;;) {
133 ret = poll(&pollfd, 1, -1);
134
135 // Poll interrupted, try again.
136 if (ret == -1 && (errno == EINTR || errno == EAGAIN)) {
137 continue;
138 }
139
140 // Poll failure, abandon.
141 if (ret == -1) {
142 ALOGE("poll error: %s", strerror(errno));
143 break;
144 }
145
146 // Spurious wakeup, try again.
147 if (ret == 0 || (pollfd.revents & POLLIN) == 0) {
148 continue;
149 }
150
151 // Read the next control event.
152 struct mgmt_pkt ev {};
153 ret = read(fd, &ev, sizeof(ev));
154 if (ret < 0) {
155 ALOGE("error reading mgmt event: %s", strerror(errno));
156 goto end;
157 }
158
159 // Received [Read Index List] command response.
160 if (ev.opcode == MGMT_EV_CMD_COMPLETE) {
161 struct mgmt_ev_read_index_list* data =
162 (struct mgmt_ev_read_index_list*)ev.data;
163
164 for (int i = 0; i < data->num_controllers; i++) {
165 if (data->index[i] == hci_interface) {
166 ALOGI("hci interface %d found", hci_interface);
167 ret = 0;
168 goto end;
169 }
170 }
171 }
172
173 // Received [Index Added] event.
174 if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) {
175 ALOGI("hci interface %d added", hci_interface);
176 ret = 0;
177 goto end;
178 }
179 }
180
181 end:
182 ::close(fd);
183 return ret;
184 }
185
openRfkill()186 int NetBluetoothMgmt::openRfkill() {
187 int fd = open("/dev/rfkill", O_RDWR);
188 if (fd < 0) {
189 ALOGE("unable to open /dev/rfkill: %s", strerror(errno));
190 return -1;
191 }
192
193 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
194 ALOGE("unable to set rfkill control device to non-blocking: %s",
195 strerror(errno));
196 ::close(fd);
197 return -1;
198 }
199
200 for (;;) {
201 struct rfkill_event event {};
202 ssize_t res = read(fd, &event, sizeof(event));
203 if (res < 0) {
204 ALOGE("error reading rfkill events: %s", strerror(errno));
205 break;
206 }
207
208 ALOGI("index:%d type:%d op:%d", event.idx, event.type, event.op);
209
210 if (event.op == RFKILL_OP_ADD && event.type == RFKILL_TYPE_BLUETOOTH) {
211 rfkill_bt_index_ = event.idx;
212 rfkill_fd_ = fd;
213 return 0;
214 }
215 }
216
217 ::close(fd);
218 return -1;
219 }
220
221 // Block or unblock Bluetooth.
rfkill(int block)222 int NetBluetoothMgmt::rfkill(int block) {
223 if (rfkill_fd_ == -1) {
224 openRfkill();
225 }
226
227 if (rfkill_fd_ == -1) {
228 ALOGE("rfkill unavailable");
229 return -1;
230 }
231
232 struct rfkill_event event = {
233 .idx = static_cast<uint32_t>(rfkill_bt_index_),
234 .type = RFKILL_TYPE_BLUETOOTH,
235 .op = RFKILL_OP_CHANGE,
236 .soft = static_cast<uint8_t>(block),
237 .hard = 0,
238 };
239
240 int res = write(rfkill_fd_, &event, sizeof(event));
241 if (res < 0) {
242 ALOGE("error writing rfkill command: %s", strerror(errno));
243 return -1;
244 }
245
246 return 0;
247 }
248
openHci(int hci_interface)249 int NetBluetoothMgmt::openHci(int hci_interface) {
250 ALOGI("opening hci interface %d", hci_interface);
251
252 // Block Bluetooth.
253 rfkill(1);
254
255 // Wait for the HCI interface to complete initialization or to come online.
256 if (waitHciDev(hci_interface)) {
257 ALOGE("hci interface %d not found", hci_interface);
258 return -1;
259 }
260
261 // Open the raw HCI socket.
262 int fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
263 if (fd < 0) {
264 ALOGE("unable to open raw bluetooth socket: %s", strerror(errno));
265 return -1;
266 }
267
268 struct sockaddr_hci hci_addr = {
269 .hci_family = AF_BLUETOOTH,
270 .hci_dev = static_cast<uint16_t>(hci_interface),
271 .hci_channel = HCI_CHANNEL_USER,
272 };
273
274 // Bind the socket to the selected interface.
275 if (bind(fd, (struct sockaddr*)&hci_addr, sizeof(hci_addr)) < 0) {
276 ALOGE("unable to bind bluetooth user channel: %s", strerror(errno));
277 ::close(fd);
278 return -1;
279 }
280
281 ALOGI("hci interface %d ready", hci_interface);
282 bt_fd_ = fd;
283 return fd;
284 }
285
closeHci()286 void NetBluetoothMgmt::closeHci() {
287 if (bt_fd_ != -1) {
288 ::close(bt_fd_);
289 bt_fd_ = -1;
290 }
291
292 // Unblock Bluetooth.
293 rfkill(0);
294 }
295
296 } // namespace aidl::android::hardware::bluetooth::impl
297