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       // Prefer the exact hci_interface
165       for (int i = 0; i < data->num_controllers; i++) {
166         if (data->index[i] == hci_interface) {
167           ALOGI("hci interface %d found", data->index[i]);
168           ret = data->index[i];
169           goto end;
170         }
171       }
172 
173       // Accept a larger one if we can't find the exact one
174       for (int i = 0; i < data->num_controllers; i++) {
175         if (data->index[i] >= hci_interface) {
176           ALOGI("hci interface %d found", data->index[i]);
177           ret = data->index[i];
178           goto end;
179         }
180       }
181     }
182 
183     // Received [Index Added] event.
184     if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) {
185       ALOGI("hci interface %d added", hci_interface);
186       ret = hci_interface;
187       goto end;
188     }
189   }
190 
191 end:
192   ::close(fd);
193   return ret;
194 }
195 
openRfkill()196 int NetBluetoothMgmt::openRfkill() {
197   int fd = open("/dev/rfkill", O_RDWR);
198   if (fd < 0) {
199     ALOGE("unable to open /dev/rfkill: %s", strerror(errno));
200     return -1;
201   }
202 
203   if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
204     ALOGE("unable to set rfkill control device to non-blocking: %s",
205           strerror(errno));
206     ::close(fd);
207     return -1;
208   }
209 
210   for (;;) {
211     struct rfkill_event event {};
212     ssize_t res = read(fd, &event, sizeof(event));
213     if (res < 0) {
214       ALOGE("error reading rfkill events: %s", strerror(errno));
215       break;
216     }
217 
218     ALOGI("index:%d type:%d op:%d", event.idx, event.type, event.op);
219 
220     if (event.op == RFKILL_OP_ADD && event.type == RFKILL_TYPE_BLUETOOTH) {
221       rfkill_bt_index_ = event.idx;
222       rfkill_fd_ = fd;
223       return 0;
224     }
225   }
226 
227   ::close(fd);
228   return -1;
229 }
230 
231 // Block or unblock Bluetooth.
rfkill(int block)232 int NetBluetoothMgmt::rfkill(int block) {
233   if (rfkill_fd_ == -1) {
234     openRfkill();
235   }
236 
237   if (rfkill_fd_ == -1) {
238     ALOGE("rfkill unavailable");
239     return -1;
240   }
241 
242   struct rfkill_event event = {
243       .idx = static_cast<uint32_t>(rfkill_bt_index_),
244       .type = RFKILL_TYPE_BLUETOOTH,
245       .op = RFKILL_OP_CHANGE,
246       .soft = static_cast<uint8_t>(block),
247       .hard = 0,
248   };
249 
250   int res = write(rfkill_fd_, &event, sizeof(event));
251   if (res < 0) {
252     ALOGE("error writing rfkill command: %s", strerror(errno));
253     return -1;
254   }
255 
256   return 0;
257 }
258 
openHci(int hci_interface)259 int NetBluetoothMgmt::openHci(int hci_interface) {
260   ALOGI("opening hci interface %d", hci_interface);
261 
262   // Block Bluetooth.
263   rfkill(1);
264 
265   // Wait for the HCI interface to complete initialization or to come online.
266   int hci = waitHciDev(hci_interface);
267   if (hci < 0) {
268     ALOGE("hci interface %d not found", hci_interface);
269     return -1;
270   }
271 
272   // Open the raw HCI socket.
273   int fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
274   if (fd < 0) {
275     ALOGE("unable to open raw bluetooth socket: %s", strerror(errno));
276     return -1;
277   }
278 
279   struct sockaddr_hci hci_addr = {
280       .hci_family = AF_BLUETOOTH,
281       .hci_dev = static_cast<uint16_t>(hci),
282       .hci_channel = HCI_CHANNEL_USER,
283   };
284 
285   // Bind the socket to the selected interface.
286   if (bind(fd, (struct sockaddr*)&hci_addr, sizeof(hci_addr)) < 0) {
287     ALOGE("unable to bind bluetooth user channel: %s", strerror(errno));
288     ::close(fd);
289     return -1;
290   }
291 
292   ALOGI("hci interface %d ready", hci);
293   bt_fd_ = fd;
294   return fd;
295 }
296 
closeHci()297 void NetBluetoothMgmt::closeHci() {
298   if (bt_fd_ != -1) {
299     ::close(bt_fd_);
300     bt_fd_ = -1;
301   }
302 
303   // Unblock Bluetooth.
304   rfkill(0);
305 }
306 
307 }  // namespace aidl::android::hardware::bluetooth::impl
308