1 /**********************************************************************
2 *
3 * Copyright (C) 2015 Intel Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 **********************************************************************/
19
20 #define LOG_TAG "bt_vendor"
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <poll.h>
25 #include <stdbool.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <sys/ioctl.h>
31 #include <sys/socket.h>
32
33 #include "hci/include/bt_vendor_lib.h"
34 #include "osi/include/compat.h"
35 #include "osi/include/log.h"
36 #include "osi/include/osi.h"
37 #include "osi/include/properties.h"
38
39 #define BTPROTO_HCI 1
40 #define HCI_CHANNEL_USER 1
41 #define HCI_CHANNEL_CONTROL 3
42 #define HCI_DEV_NONE 0xffff
43
44 #define RFKILL_TYPE_BLUETOOTH 2
45 #define RFKILL_OP_CHANGE_ALL 3
46
47 #define MGMT_OP_INDEX_LIST 0x0003
48 #define MGMT_EV_INDEX_ADDED 0x0004
49 #define MGMT_EV_COMMAND_COMP 0x0001
50 #define MGMT_EV_SIZE_MAX 1024
51 #define MGMT_EV_POLL_TIMEOUT 3000 /* 3000ms */
52
53 #define IOCTL_HCIDEVDOWN _IOW('H', 202, int)
54
55 struct sockaddr_hci {
56 sa_family_t hci_family;
57 unsigned short hci_dev;
58 unsigned short hci_channel;
59 };
60
61 struct rfkill_event {
62 uint32_t idx;
63 uint8_t type;
64 uint8_t op;
65 uint8_t soft, hard;
66 } __attribute__((packed));
67
68 struct mgmt_pkt {
69 uint16_t opcode;
70 uint16_t index;
71 uint16_t len;
72 uint8_t data[MGMT_EV_SIZE_MAX];
73 } __attribute__((packed));
74
75 struct mgmt_event_read_index {
76 uint16_t cc_opcode;
77 uint8_t status;
78 uint16_t num_intf;
79 uint16_t index[0];
80 } __attribute__((packed));
81
82 static const bt_vendor_callbacks_t* bt_vendor_callbacks;
83 static unsigned char bt_vendor_local_bdaddr[6];
84 static int bt_vendor_fd = -1;
85 static int hci_interface;
86 static int rfkill_en;
87 static int bt_hwcfg_en;
88
bt_vendor_init(const bt_vendor_callbacks_t * p_cb,unsigned char * local_bdaddr)89 static int bt_vendor_init(const bt_vendor_callbacks_t* p_cb,
90 unsigned char* local_bdaddr) {
91 char prop_value[PROPERTY_VALUE_MAX];
92
93 LOG_INFO(LOG_TAG, "%s", __func__);
94
95 if (p_cb == NULL) {
96 LOG_ERROR(LOG_TAG, "init failed with no user callbacks!");
97 return -1;
98 }
99
100 bt_vendor_callbacks = p_cb;
101
102 memcpy(bt_vendor_local_bdaddr, local_bdaddr, sizeof(bt_vendor_local_bdaddr));
103
104 osi_property_get("bluetooth.interface", prop_value, "0");
105
106 errno = 0;
107 if (memcmp(prop_value, "hci", 3))
108 hci_interface = strtol(prop_value, NULL, 10);
109 else
110 hci_interface = strtol(prop_value + 3, NULL, 10);
111 if (errno) hci_interface = 0;
112
113 LOG_INFO(LOG_TAG, "Using interface hci%d", hci_interface);
114
115 osi_property_get("bluetooth.rfkill", prop_value, "0");
116
117 rfkill_en = atoi(prop_value);
118 if (rfkill_en) LOG_INFO(LOG_TAG, "RFKILL enabled");
119
120 bt_hwcfg_en =
121 osi_property_get("bluetooth.hwcfg", prop_value, NULL) > 0 ? 1 : 0;
122 if (bt_hwcfg_en) LOG_INFO(LOG_TAG, "HWCFG enabled");
123
124 return 0;
125 }
126
bt_vendor_hw_cfg(int stop)127 static int bt_vendor_hw_cfg(int stop) {
128 if (!bt_hwcfg_en) return 0;
129
130 if (stop) {
131 if (osi_property_set("bluetooth.hwcfg", "stop") < 0) {
132 LOG_ERROR(LOG_TAG, "%s cannot stop btcfg service via prop", __func__);
133 return 1;
134 }
135 } else {
136 if (osi_property_set("bluetooth.hwcfg", "start") < 0) {
137 LOG_ERROR(LOG_TAG, "%s cannot start btcfg service via prop", __func__);
138 return 1;
139 }
140 }
141 return 0;
142 }
143
bt_vendor_wait_hcidev(void)144 static int bt_vendor_wait_hcidev(void) {
145 struct sockaddr_hci addr;
146 struct pollfd fds[1];
147 struct mgmt_pkt ev;
148 int fd;
149 int ret = 0;
150
151 LOG_INFO(LOG_TAG, "%s", __func__);
152
153 fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
154 if (fd < 0) {
155 LOG_ERROR(LOG_TAG, "Bluetooth socket error: %s", strerror(errno));
156 return -1;
157 }
158
159 memset(&addr, 0, sizeof(addr));
160 addr.hci_family = AF_BLUETOOTH;
161 addr.hci_dev = HCI_DEV_NONE;
162 addr.hci_channel = HCI_CHANNEL_CONTROL;
163
164 if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
165 LOG_ERROR(LOG_TAG, "HCI Channel Control: %s", strerror(errno));
166 close(fd);
167 return -1;
168 }
169
170 fds[0].fd = fd;
171 fds[0].events = POLLIN;
172
173 /* Read Controller Index List Command */
174 ev.opcode = MGMT_OP_INDEX_LIST;
175 ev.index = HCI_DEV_NONE;
176 ev.len = 0;
177
178 ssize_t wrote;
179 OSI_NO_INTR(wrote = write(fd, &ev, 6));
180 if (wrote != 6) {
181 LOG_ERROR(LOG_TAG, "Unable to write mgmt command: %s", strerror(errno));
182 ret = -1;
183 goto end;
184 }
185
186 while (1) {
187 int n;
188 OSI_NO_INTR(n = poll(fds, 1, MGMT_EV_POLL_TIMEOUT));
189 if (n == -1) {
190 LOG_ERROR(LOG_TAG, "Poll error: %s", strerror(errno));
191 ret = -1;
192 break;
193 } else if (n == 0) {
194 LOG_ERROR(LOG_TAG, "Timeout, no HCI device detected");
195 ret = -1;
196 break;
197 }
198
199 if (fds[0].revents & POLLIN) {
200 OSI_NO_INTR(n = read(fd, &ev, sizeof(struct mgmt_pkt)));
201 if (n < 0) {
202 LOG_ERROR(LOG_TAG, "Error reading control channel: %s",
203 strerror(errno));
204 ret = -1;
205 break;
206 }
207
208 if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) {
209 goto end;
210 } else if (ev.opcode == MGMT_EV_COMMAND_COMP) {
211 struct mgmt_event_read_index* cc;
212 int i;
213
214 cc = (struct mgmt_event_read_index*)ev.data;
215
216 if (cc->cc_opcode != MGMT_OP_INDEX_LIST || cc->status != 0) continue;
217
218 for (i = 0; i < cc->num_intf; i++) {
219 if (cc->index[i] == hci_interface) goto end;
220 }
221 }
222 }
223 }
224
225 end:
226 close(fd);
227 return ret;
228 }
229
bt_vendor_open(void * param)230 static int bt_vendor_open(void* param) {
231 int(*fd_array)[] = (int(*)[])param;
232 int fd;
233
234 LOG_INFO(LOG_TAG, "%s", __func__);
235
236 fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
237 if (fd < 0) {
238 LOG_ERROR(LOG_TAG, "socket create error %s", strerror(errno));
239 return -1;
240 }
241
242 (*fd_array)[CH_CMD] = fd;
243 (*fd_array)[CH_EVT] = fd;
244 (*fd_array)[CH_ACL_OUT] = fd;
245 (*fd_array)[CH_ACL_IN] = fd;
246
247 bt_vendor_fd = fd;
248
249 LOG_INFO(LOG_TAG, "%s returning %d", __func__, bt_vendor_fd);
250
251 return 1;
252 }
253
bt_vendor_close(void * param)254 static int bt_vendor_close(void* param) {
255 (void)(param);
256
257 LOG_INFO(LOG_TAG, "%s", __func__);
258
259 if (bt_vendor_fd != -1) {
260 close(bt_vendor_fd);
261 bt_vendor_fd = -1;
262 }
263
264 return 0;
265 }
266
bt_vendor_rfkill(int block)267 static int bt_vendor_rfkill(int block) {
268 struct rfkill_event event;
269 int fd;
270
271 LOG_INFO(LOG_TAG, "%s", __func__);
272
273 fd = open("/dev/rfkill", O_WRONLY);
274 if (fd < 0) {
275 LOG_ERROR(LOG_TAG, "Unable to open /dev/rfkill");
276 return -1;
277 }
278
279 memset(&event, 0, sizeof(struct rfkill_event));
280 event.op = RFKILL_OP_CHANGE_ALL;
281 event.type = RFKILL_TYPE_BLUETOOTH;
282 event.hard = block;
283 event.soft = block;
284
285 ssize_t len;
286 OSI_NO_INTR(len = write(fd, &event, sizeof(event)));
287 if (len < 0) {
288 LOG_ERROR(LOG_TAG, "Failed to change rfkill state");
289 close(fd);
290 return 1;
291 }
292
293 close(fd);
294 return 0;
295 }
296
297 /* TODO: fw config should thread the device waiting and return immedialty */
bt_vendor_fw_cfg(void)298 static void bt_vendor_fw_cfg(void) {
299 struct sockaddr_hci addr;
300 int fd = bt_vendor_fd;
301
302 LOG_INFO(LOG_TAG, "%s", __func__);
303
304 if (fd == -1) {
305 LOG_ERROR(LOG_TAG, "bt_vendor_fd: %s", strerror(EBADF));
306 goto failure;
307 }
308
309 memset(&addr, 0, sizeof(addr));
310 addr.hci_family = AF_BLUETOOTH;
311 addr.hci_dev = hci_interface;
312 addr.hci_channel = HCI_CHANNEL_USER;
313
314 if (bt_vendor_wait_hcidev()) {
315 LOG_ERROR(LOG_TAG, "HCI interface (%d) not found", hci_interface);
316 goto failure;
317 }
318
319 if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
320 LOG_ERROR(LOG_TAG, "socket bind error %s", strerror(errno));
321 goto failure;
322 }
323
324 LOG_INFO(LOG_TAG, "HCI device ready");
325
326 bt_vendor_callbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
327
328 return;
329
330 failure:
331 LOG_ERROR(LOG_TAG, "Hardware Config Error");
332 bt_vendor_callbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
333 }
334
bt_vendor_op(bt_vendor_opcode_t opcode,void * param)335 static int bt_vendor_op(bt_vendor_opcode_t opcode, void* param) {
336 int retval = 0;
337
338 LOG_INFO(LOG_TAG, "%s op %d", __func__, opcode);
339
340 switch (opcode) {
341 case BT_VND_OP_POWER_CTRL:
342 if (!rfkill_en || !param) break;
343
344 if (*((int*)param) == BT_VND_PWR_ON) {
345 retval = bt_vendor_rfkill(0);
346 if (!retval) retval = bt_vendor_hw_cfg(0);
347 } else {
348 retval = bt_vendor_hw_cfg(1);
349 if (!retval) retval = bt_vendor_rfkill(1);
350 }
351
352 break;
353
354 case BT_VND_OP_FW_CFG:
355 bt_vendor_fw_cfg();
356 break;
357
358 case BT_VND_OP_SCO_CFG:
359 bt_vendor_callbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
360 break;
361
362 case BT_VND_OP_USERIAL_OPEN:
363 retval = bt_vendor_open(param);
364 break;
365
366 case BT_VND_OP_USERIAL_CLOSE:
367 retval = bt_vendor_close(param);
368 break;
369
370 case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
371 *((uint32_t*)param) = 3000;
372 retval = 0;
373 break;
374
375 case BT_VND_OP_LPM_SET_MODE:
376 bt_vendor_callbacks->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
377 break;
378
379 case BT_VND_OP_LPM_WAKE_SET_STATE:
380 break;
381
382 case BT_VND_OP_SET_AUDIO_STATE:
383 bt_vendor_callbacks->audio_state_cb(BT_VND_OP_RESULT_SUCCESS);
384 break;
385
386 case BT_VND_OP_EPILOG:
387 bt_vendor_callbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
388 break;
389
390 case BT_VND_OP_A2DP_OFFLOAD_START:
391 break;
392
393 case BT_VND_OP_A2DP_OFFLOAD_STOP:
394 break;
395 }
396
397 LOG_INFO(LOG_TAG, "%s op %d retval %d", __func__, opcode, retval);
398
399 return retval;
400 }
401
bt_vendor_cleanup(void)402 static void bt_vendor_cleanup(void) {
403 LOG_INFO(LOG_TAG, "%s", __func__);
404
405 bt_vendor_callbacks = NULL;
406 }
407
408 EXPORT_SYMBOL const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
409 sizeof(bt_vendor_interface_t), bt_vendor_init, bt_vendor_op,
410 bt_vendor_cleanup,
411 };
412