OSDN Git Service

DO NOT MERGE Revert "Always send a SUSPEND_CFM event when suspended due to A2DP RECON...
[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   if (write(fd, &ev, 6) != 6) {
183     LOG_ERROR(LOG_TAG, "Unable to write mgmt command: %s", strerror(errno));
184     ret = -1;
185     goto end;
186   }
187
188   while (1) {
189     int n = poll(fds, 1, MGMT_EV_POLL_TIMEOUT);
190     if (n == -1) {
191       LOG_ERROR(LOG_TAG, "Poll error: %s", strerror(errno));
192       ret = -1;
193       break;
194     } else if (n == 0) {
195       LOG_ERROR(LOG_TAG, "Timeout, no HCI device detected");
196       ret = -1;
197       break;
198     }
199
200     if (fds[0].revents & POLLIN) {
201       n = read(fd, &ev, sizeof(struct mgmt_pkt));
202       if (n < 0) {
203         LOG_ERROR(LOG_TAG,
204                   "Error reading control channel");
205         ret = -1;
206         break;
207       }
208
209       if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) {
210         goto end;
211       } else if (ev.opcode == MGMT_EV_COMMAND_COMP) {
212         struct mgmt_event_read_index *cc;
213         int i;
214
215         cc = (struct mgmt_event_read_index *)ev.data;
216
217         if (cc->cc_opcode != MGMT_OP_INDEX_LIST || cc->status != 0)
218           continue;
219
220         for (i = 0; i < cc->num_intf; i++) {
221           if (cc->index[i] == hci_interface)
222             goto end;
223         }
224       }
225     }
226   }
227
228 end:
229   close(fd);
230   return ret;
231 }
232
233 static int bt_vendor_open(void *param)
234 {
235   int (*fd_array)[] = (int (*)[]) param;
236   int fd;
237
238   LOG_INFO(LOG_TAG, "%s", __func__);
239
240   fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
241   if (fd < 0) {
242     LOG_ERROR(LOG_TAG, "socket create error %s", strerror(errno));
243     return -1;
244   }
245
246   (*fd_array)[CH_CMD] = fd;
247   (*fd_array)[CH_EVT] = fd;
248   (*fd_array)[CH_ACL_OUT] = fd;
249   (*fd_array)[CH_ACL_IN] = fd;
250
251   bt_vendor_fd = fd;
252
253   LOG_INFO(LOG_TAG, "%s returning %d", __func__, bt_vendor_fd);
254
255   return 1;
256 }
257
258 static int bt_vendor_close(void *param)
259 {
260   (void)(param);
261
262   LOG_INFO(LOG_TAG, "%s", __func__);
263
264   if (bt_vendor_fd != -1) {
265     close(bt_vendor_fd);
266     bt_vendor_fd = -1;
267   }
268
269   return 0;
270 }
271
272 static int bt_vendor_rfkill(int block)
273 {
274   struct rfkill_event event;
275   int fd, len;
276
277   LOG_INFO(LOG_TAG, "%s", __func__);
278
279   fd = open("/dev/rfkill", O_WRONLY);
280   if (fd < 0) {
281     LOG_ERROR(LOG_TAG, "Unable to open /dev/rfkill");
282     return -1;
283   }
284
285   memset(&event, 0, sizeof(struct rfkill_event));
286   event.op = RFKILL_OP_CHANGE_ALL;
287   event.type = RFKILL_TYPE_BLUETOOTH;
288   event.hard = block;
289   event.soft = block;
290
291   len = write(fd, &event, sizeof(event));
292   if (len < 0) {
293     LOG_ERROR(LOG_TAG, "Failed to change rfkill state");
294     close(fd);
295     return 1;
296   }
297
298   close(fd);
299   return 0;
300 }
301
302 /* TODO: fw config should thread the device waiting and return immedialty */
303 static void bt_vendor_fw_cfg(void)
304 {
305   struct sockaddr_hci addr;
306   int fd = bt_vendor_fd;
307
308   LOG_INFO(LOG_TAG, "%s", __func__);
309
310   if (fd == -1) {
311     LOG_ERROR(LOG_TAG, "bt_vendor_fd: %s", strerror(EBADF));
312     goto failure;
313   }
314
315   memset(&addr, 0, sizeof(addr));
316   addr.hci_family = AF_BLUETOOTH;
317   addr.hci_dev = hci_interface;
318   addr.hci_channel = HCI_CHANNEL_USER;
319
320   if (bt_vendor_wait_hcidev()) {
321     LOG_ERROR(LOG_TAG, "HCI interface (%d) not found", hci_interface);
322     goto failure;
323   }
324
325   if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
326     LOG_ERROR(LOG_TAG, "socket bind error %s", strerror(errno));
327     goto failure;
328   }
329
330   LOG_INFO(LOG_TAG, "HCI device ready");
331
332   bt_vendor_callbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
333
334   return;
335
336 failure:
337   LOG_ERROR(LOG_TAG, "Hardware Config Error");
338   bt_vendor_callbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
339 }
340
341 static int bt_vendor_op(bt_vendor_opcode_t opcode, void *param)
342 {
343   int retval = 0;
344
345   LOG_INFO(LOG_TAG, "%s op %d", __func__, opcode);
346
347   switch (opcode) {
348   case BT_VND_OP_POWER_CTRL:
349     if (!rfkill_en || !param)
350       break;
351
352     if (*((int *)param) == BT_VND_PWR_ON) {
353       retval = bt_vendor_rfkill(0);
354       if (!retval)
355         retval = bt_vendor_hw_cfg(0);
356     } else {
357       retval = bt_vendor_hw_cfg(1);
358       if (!retval)
359         retval = bt_vendor_rfkill(1);
360     }
361
362     break;
363
364   case BT_VND_OP_FW_CFG:
365     bt_vendor_fw_cfg();
366     break;
367
368   case BT_VND_OP_SCO_CFG:
369     bt_vendor_callbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
370     break;
371
372   case BT_VND_OP_USERIAL_OPEN:
373     retval = bt_vendor_open(param);
374     break;
375
376   case BT_VND_OP_USERIAL_CLOSE:
377     retval = bt_vendor_close(param);
378     break;
379
380   case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
381     *((uint32_t *)param) = 3000;
382     retval = 0;
383     break;
384
385   case BT_VND_OP_LPM_SET_MODE:
386     bt_vendor_callbacks->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
387     break;
388
389   case BT_VND_OP_LPM_WAKE_SET_STATE:
390     break;
391
392   case BT_VND_OP_SET_AUDIO_STATE:
393     bt_vendor_callbacks->audio_state_cb(BT_VND_OP_RESULT_SUCCESS);
394     break;
395
396   case BT_VND_OP_EPILOG:
397     bt_vendor_callbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
398     break;
399   }
400
401   LOG_INFO(LOG_TAG, "%s op %d retval %d", __func__, opcode, retval);
402
403   return retval;
404 }
405
406 static void bt_vendor_cleanup(void)
407 {
408   LOG_INFO(LOG_TAG, "%s", __func__);
409
410   bt_vendor_callbacks = NULL;
411 }
412
413 EXPORT_SYMBOL const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
414   sizeof(bt_vendor_interface_t),
415   bt_vendor_init,
416   bt_vendor_op,
417   bt_vendor_cleanup,
418 };