OSDN Git Service

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