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