OSDN Git Service

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