system/bt
リビジョン | 3bd68219c0d40be794eb3463b70092896ca31673 (tree) |
---|---|
日時 | 2019-11-14 13:21:27 |
作者 | Chih-Wei Huang <cwhuang@linu...> |
コミッター | Chih-Wei Huang |
Replace Bluetooth HAL by Intel's implementation
Linaro's implementation is buggy.
@@ -17,27 +17,36 @@ cc_binary { | ||
17 | 17 | name: "android.hardware.bluetooth@1.0-service.btlinux", |
18 | 18 | proprietary: true, |
19 | 19 | relative_install_path: "hw", |
20 | + include_dirs: [ | |
21 | + "system/bt/device/include", | |
22 | + "system/bt/stack/include" | |
23 | + ], | |
20 | 24 | srcs: [ |
25 | + "async_fd_watcher.cc", | |
26 | + "bluetooth_hci.cc", | |
27 | + "bluetooth_address.cc", | |
28 | + "vendor_interface.cc", | |
21 | 29 | "hci_packetizer.cc", |
30 | + "hci_protocol.cc", | |
22 | 31 | "h4_protocol.cc", |
23 | - "bluetooth_hci.cc", | |
24 | - "async_fd_watcher.cc", | |
32 | + "mct_protocol.cc", | |
25 | 33 | "service.cc" |
26 | 34 | ], |
27 | - cflags: ["-Wall", "-Werror"], | |
35 | + cflags: ["-Wall", "-Werror", "-Wno-unused-result"], | |
28 | 36 | header_libs: ["libbluetooth_headers"], |
29 | 37 | shared_libs: [ |
30 | 38 | "android.hardware.bluetooth@1.0", |
31 | 39 | "libbase", |
32 | 40 | "libcutils", |
41 | + "libhwbinder", | |
33 | 42 | "libhidlbase", |
34 | 43 | "libhidltransport", |
35 | 44 | "liblog", |
36 | 45 | "libutils", |
46 | + "libusb", | |
37 | 47 | ], |
38 | - conlyflags: [ | |
39 | - "-std=c99", | |
48 | + required: [ | |
49 | + "libbt-vendor", | |
40 | 50 | ], |
41 | 51 | init_rc: ["android.hardware.bluetooth@1.0-service.btlinux.rc"], |
42 | 52 | } |
43 | - |
@@ -1,5 +1,15 @@ | ||
1 | -service btlinux-1.0 /vendor/bin/hw/android.hardware.bluetooth@1.0-service.btlinux | |
1 | +service vendor.bluetooth-1-0 /vendor/bin/hw/android.hardware.bluetooth@1.0-service.btlinux | |
2 | 2 | class hal |
3 | + capabilities BLOCK_SUSPEND NET_ADMIN SYS_NICE | |
3 | 4 | user bluetooth |
4 | - group bluetooth net_admin net_bt_admin | |
5 | - capabilities NET_ADMIN | |
5 | + group bluetooth | |
6 | + writepid /dev/stune/foreground/tasks | |
7 | + | |
8 | +on property:vts.native_server.on=1 && property:ro.build.type=userdebug | |
9 | + stop vendor.bluetooth-1-0 | |
10 | +on property:vts.native_server.on=1 && property:ro.build.type=eng | |
11 | + stop vendor.bluetooth-1-0 | |
12 | +on property:vts.native_server.on=0 && property:ro.build.type=userdebug | |
13 | + start vendor.bluetooth-1-0 | |
14 | +on property:vts.native_server.on=0 && property:ro.build.type=eng | |
15 | + start vendor.bluetooth-1-0 |
@@ -14,21 +14,24 @@ | ||
14 | 14 | // limitations under the License. |
15 | 15 | // |
16 | 16 | |
17 | +#define LOG_TAG "android.hardware.bluetooth@1.0-service.btlinux" | |
18 | + | |
17 | 19 | #include "async_fd_watcher.h" |
18 | 20 | |
19 | 21 | #include <algorithm> |
20 | 22 | #include <atomic> |
21 | 23 | #include <condition_variable> |
22 | -#include <log/log.h> | |
23 | 24 | #include <map> |
24 | 25 | #include <mutex> |
25 | 26 | #include <thread> |
27 | +#include <log/log.h> | |
26 | 28 | #include <vector> |
27 | 29 | #include "fcntl.h" |
28 | 30 | #include "sys/select.h" |
29 | 31 | #include "unistd.h" |
30 | 32 | |
31 | 33 | static const int INVALID_FD = -1; |
34 | + | |
32 | 35 | static const int BT_RT_PRIORITY = 1; |
33 | 36 | |
34 | 37 | namespace android { |
@@ -102,6 +105,9 @@ int AsyncFdWatcher::stopThread() { | ||
102 | 105 | timeout_cb_ = nullptr; |
103 | 106 | } |
104 | 107 | |
108 | + close(notification_listen_fd_); | |
109 | + close(notification_write_fd_); | |
110 | + | |
105 | 111 | return 0; |
106 | 112 | } |
107 | 113 |
@@ -114,7 +120,6 @@ int AsyncFdWatcher::notifyThread() { | ||
114 | 120 | } |
115 | 121 | |
116 | 122 | void AsyncFdWatcher::ThreadRoutine() { |
117 | - | |
118 | 123 | // Make watching thread RT. |
119 | 124 | struct sched_param rt_params; |
120 | 125 | rt_params.sched_priority = BT_RT_PRIORITY; |
@@ -0,0 +1,128 @@ | ||
1 | +// | |
2 | +// Copyright 2016 The Android Open Source Project | |
3 | +// | |
4 | +// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +// you may not use this file except in compliance with the License. | |
6 | +// You may obtain a copy of the License at | |
7 | +// | |
8 | +// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +// | |
10 | +// Unless required by applicable law or agreed to in writing, software | |
11 | +// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +// See the License for the specific language governing permissions and | |
14 | +// limitations under the License. | |
15 | +// | |
16 | + | |
17 | +#include "bluetooth_address.h" | |
18 | + | |
19 | +#include <cutils/properties.h> | |
20 | +#include <errno.h> | |
21 | +#include <fcntl.h> | |
22 | +#include <unistd.h> | |
23 | +#include <utils/Log.h> | |
24 | + | |
25 | +namespace android { | |
26 | +namespace hardware { | |
27 | +namespace bluetooth { | |
28 | +namespace V1_0 { | |
29 | +namespace implementation { | |
30 | + | |
31 | +void BluetoothAddress::bytes_to_string(const uint8_t* addr, char* addr_str) { | |
32 | + sprintf(addr_str, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], | |
33 | + addr[3], addr[4], addr[5]); | |
34 | +} | |
35 | + | |
36 | +bool BluetoothAddress::string_to_bytes(const char* addr_str, uint8_t* addr) { | |
37 | + if (addr_str == NULL) return false; | |
38 | + if (strnlen(addr_str, kStringLength) != kStringLength) return false; | |
39 | + unsigned char trailing_char = '\0'; | |
40 | + | |
41 | + return (sscanf(addr_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx%1c", | |
42 | + &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5], | |
43 | + &trailing_char) == kBytes); | |
44 | +} | |
45 | + | |
46 | +bool BluetoothAddress::get_local_address(uint8_t* local_addr) { | |
47 | + char property[PROPERTY_VALUE_MAX] = {0}; | |
48 | + bool valid_bda = false; | |
49 | + | |
50 | + // Get local bdaddr storage path from a system property. | |
51 | + if (property_get(PROPERTY_BT_BDADDR_PATH, property, NULL)) { | |
52 | + int addr_fd; | |
53 | + | |
54 | + ALOGD("%s: Trying %s", __func__, property); | |
55 | + | |
56 | + addr_fd = open(property, O_RDONLY); | |
57 | + if (addr_fd != -1) { | |
58 | + char address[kStringLength + 1] = {0}; | |
59 | + int bytes_read = read(addr_fd, address, kStringLength); | |
60 | + if (bytes_read == -1) { | |
61 | + ALOGE("%s: Error reading address from %s: %s", __func__, property, | |
62 | + strerror(errno)); | |
63 | + } | |
64 | + close(addr_fd); | |
65 | + | |
66 | + // Null terminate the string. | |
67 | + address[kStringLength] = '\0'; | |
68 | + | |
69 | + // If the address is not all zeros, then use it. | |
70 | + const uint8_t zero_bdaddr[kBytes] = {0, 0, 0, 0, 0, 0}; | |
71 | + if ((string_to_bytes(address, local_addr)) && | |
72 | + (memcmp(local_addr, zero_bdaddr, kBytes) != 0)) { | |
73 | + valid_bda = true; | |
74 | + ALOGD("%s: Got Factory BDA %s", __func__, address); | |
75 | + } else { | |
76 | + ALOGE("%s: Got Invalid BDA '%s' from %s", __func__, address, property); | |
77 | + } | |
78 | + } | |
79 | + } | |
80 | + | |
81 | + // No BDADDR found in the file. Look for BDA in a factory property. | |
82 | + if (!valid_bda && property_get(FACTORY_BDADDR_PROPERTY, property, NULL) && | |
83 | + string_to_bytes(property, local_addr)) { | |
84 | + valid_bda = true; | |
85 | + } | |
86 | + | |
87 | + // No factory BDADDR found. Look for a previously stored BDA. | |
88 | + if (!valid_bda && property_get(PERSIST_BDADDR_PROPERTY, property, NULL) && | |
89 | + string_to_bytes(property, local_addr)) { | |
90 | + valid_bda = true; | |
91 | + } | |
92 | + | |
93 | + /* Generate new BDA if necessary */ | |
94 | + if (!valid_bda) { | |
95 | + char bdstr[kStringLength + 1]; | |
96 | + | |
97 | + /* No autogen BDA. Generate one now. */ | |
98 | + local_addr[0] = 0x22; | |
99 | + local_addr[1] = 0x22; | |
100 | + local_addr[2] = (uint8_t)rand(); | |
101 | + local_addr[3] = (uint8_t)rand(); | |
102 | + local_addr[4] = (uint8_t)rand(); | |
103 | + local_addr[5] = (uint8_t)rand(); | |
104 | + | |
105 | + /* Convert to ascii, and store as a persistent property */ | |
106 | + bytes_to_string(local_addr, bdstr); | |
107 | + | |
108 | + ALOGE("%s: No preset BDA! Generating BDA: %s for prop %s", __func__, | |
109 | + (char*)bdstr, PERSIST_BDADDR_PROPERTY); | |
110 | + ALOGE("%s: This is a bug in the platform! Please fix!", __func__); | |
111 | + | |
112 | + if (property_set(PERSIST_BDADDR_PROPERTY, (char*)bdstr) < 0) { | |
113 | + ALOGE("%s: Failed to set random BDA in prop %s", __func__, | |
114 | + PERSIST_BDADDR_PROPERTY); | |
115 | + valid_bda = false; | |
116 | + } else { | |
117 | + valid_bda = true; | |
118 | + } | |
119 | + } | |
120 | + | |
121 | + return valid_bda; | |
122 | +} | |
123 | + | |
124 | +} // namespace implementation | |
125 | +} // namespace V1_0 | |
126 | +} // namespace bluetooth | |
127 | +} // namespace hardware | |
128 | +} // namespace android |
@@ -0,0 +1,61 @@ | ||
1 | +// | |
2 | +// Copyright 2016 The Android Open Source Project | |
3 | +// | |
4 | +// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +// you may not use this file except in compliance with the License. | |
6 | +// You may obtain a copy of the License at | |
7 | +// | |
8 | +// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +// | |
10 | +// Unless required by applicable law or agreed to in writing, software | |
11 | +// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +// See the License for the specific language governing permissions and | |
14 | +// limitations under the License. | |
15 | +// | |
16 | + | |
17 | +#pragma once | |
18 | + | |
19 | +#include <fcntl.h> | |
20 | + | |
21 | +#include <cstdint> | |
22 | +#include <string> | |
23 | +#include <vector> | |
24 | + | |
25 | +namespace android { | |
26 | +namespace hardware { | |
27 | +namespace bluetooth { | |
28 | +namespace V1_0 { | |
29 | +namespace implementation { | |
30 | + | |
31 | +// The property key stores the storage location of Bluetooth Device Address | |
32 | +static constexpr char PROPERTY_BT_BDADDR_PATH[] = "ro.bt.bdaddr_path"; | |
33 | + | |
34 | +// Check for a legacy address stored as a property. | |
35 | +static constexpr char PERSIST_BDADDR_PROPERTY[] = | |
36 | + "persist.service.bdroid.bdaddr"; | |
37 | + | |
38 | +// If there is no valid bdaddr available from PROPERTY_BT_BDADDR_PATH and there | |
39 | +// is no available persistent bdaddr available from PERSIST_BDADDR_PROPERTY, | |
40 | +// use a factory set address. | |
41 | +static constexpr char FACTORY_BDADDR_PROPERTY[] = "ro.boot.btmacaddr"; | |
42 | + | |
43 | +// Encapsulate handling for Bluetooth Addresses: | |
44 | +class BluetoothAddress { | |
45 | + public: | |
46 | + // Conversion constants | |
47 | + static constexpr size_t kStringLength = sizeof("XX:XX:XX:XX:XX:XX") - 1; | |
48 | + static constexpr size_t kBytes = (kStringLength + 1) / 3; | |
49 | + | |
50 | + static void bytes_to_string(const uint8_t* addr, char* addr_str); | |
51 | + | |
52 | + static bool string_to_bytes(const char* addr_str, uint8_t* addr); | |
53 | + | |
54 | + static bool get_local_address(uint8_t* addr); | |
55 | +}; | |
56 | + | |
57 | +} // namespace implementation | |
58 | +} // namespace V1_0 | |
59 | +} // namespace bluetooth | |
60 | +} // namespace hardware | |
61 | +} // namespace android |
@@ -14,233 +14,22 @@ | ||
14 | 14 | // limitations under the License. |
15 | 15 | // |
16 | 16 | |
17 | -#define LOG_TAG "android.hardware.bluetooth@1.0-btlinux" | |
18 | -#include <errno.h> | |
19 | -#include <fcntl.h> | |
20 | -#include <poll.h> | |
21 | -#include <stdint.h> | |
22 | -#include <stdlib.h> | |
23 | -#include <string.h> | |
24 | - | |
25 | -#include <sys/socket.h> | |
26 | - | |
27 | -#include <utils/Log.h> | |
28 | - | |
17 | +#define LOG_TAG "android.hardware.bluetooth@1.0-service.btlinux" | |
29 | 18 | #include "bluetooth_hci.h" |
30 | 19 | |
31 | -#define BTPROTO_HCI 1 | |
32 | - | |
33 | -#define HCI_CHANNEL_USER 1 | |
34 | -#define HCI_CHANNEL_CONTROL 3 | |
35 | -#define HCI_DEV_NONE 0xffff | |
36 | - | |
37 | -/* reference from <kernel>/include/net/bluetooth/mgmt.h */ | |
38 | -#define MGMT_OP_INDEX_LIST 0x0003 | |
39 | -#define MGMT_EV_INDEX_ADDED 0x0004 | |
40 | -#define MGMT_EV_COMMAND_COMP 0x0001 | |
41 | -#define MGMT_EV_SIZE_MAX 1024 | |
42 | -#define MGMT_EV_POLL_TIMEOUT 3000 /* 3000ms */ | |
43 | -#define WRITE_NO_INTR(fn) \ | |
44 | - do { \ | |
45 | - } while ((fn) == -1 && errno == EINTR) | |
46 | - | |
47 | -struct sockaddr_hci { | |
48 | - sa_family_t hci_family; | |
49 | - unsigned short hci_dev; | |
50 | - unsigned short hci_channel; | |
51 | -}; | |
52 | - | |
53 | -struct mgmt_pkt { | |
54 | - uint16_t opcode; | |
55 | - uint16_t index; | |
56 | - uint16_t len; | |
57 | - uint8_t data[MGMT_EV_SIZE_MAX]; | |
58 | -} __attribute__((packed)); | |
20 | +#include <log/log.h> | |
59 | 21 | |
60 | -struct mgmt_event_read_index { | |
61 | - uint16_t cc_opcode; | |
62 | - uint8_t status; | |
63 | - uint16_t num_intf; | |
64 | - uint16_t index[0]; | |
65 | - } __attribute__((packed)); | |
22 | +#include "vendor_interface.h" | |
66 | 23 | |
67 | 24 | namespace android { |
68 | 25 | namespace hardware { |
69 | 26 | namespace bluetooth { |
70 | 27 | namespace V1_0 { |
71 | -namespace btlinux { | |
72 | - | |
73 | -int BluetoothHci::openBtHci() { | |
74 | - | |
75 | - ALOGI( "%s", __func__); | |
76 | - | |
77 | - int hci_interface = 0; | |
78 | - rfkill_state_ = NULL; | |
79 | - rfKill(1); | |
80 | - | |
81 | - int fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); | |
82 | - if (fd < 0) { | |
83 | - ALOGE( "Bluetooth socket error: %s", strerror(errno)); | |
84 | - return -1; | |
85 | - } | |
86 | - bt_soc_fd_ = fd; | |
87 | - | |
88 | - if (waitHciDev(hci_interface)) { | |
89 | - ALOGE( "HCI interface (%d) not found", hci_interface); | |
90 | - ::close(fd); | |
91 | - return -1; | |
92 | - } | |
93 | - struct sockaddr_hci addr; | |
94 | - memset(&addr, 0, sizeof(addr)); | |
95 | - addr.hci_family = AF_BLUETOOTH; | |
96 | - addr.hci_dev = hci_interface; | |
97 | - addr.hci_channel = HCI_CHANNEL_USER; | |
98 | - if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { | |
99 | - ALOGE( "HCI Channel Control: %s", strerror(errno)); | |
100 | - ::close(fd); | |
101 | - return -1; | |
102 | - } | |
103 | - ALOGI( "HCI device ready"); | |
104 | - return fd; | |
105 | -} | |
106 | - | |
107 | -void BluetoothHci::closeBtHci() { | |
108 | - if (bt_soc_fd_ != -1) { | |
109 | - ::close(bt_soc_fd_); | |
110 | - bt_soc_fd_ = -1; | |
111 | - } | |
112 | - rfKill(0); | |
113 | - free(rfkill_state_); | |
114 | -} | |
115 | - | |
116 | -int BluetoothHci::waitHciDev(int hci_interface) { | |
117 | - struct sockaddr_hci addr; | |
118 | - struct pollfd fds[1]; | |
119 | - struct mgmt_pkt ev; | |
120 | - int fd; | |
121 | - int ret = 0; | |
122 | - | |
123 | - ALOGI( "%s", __func__); | |
124 | - fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); | |
125 | - if (fd < 0) { | |
126 | - ALOGE( "Bluetooth socket error: %s", strerror(errno)); | |
127 | - return -1; | |
128 | - } | |
129 | - memset(&addr, 0, sizeof(addr)); | |
130 | - addr.hci_family = AF_BLUETOOTH; | |
131 | - addr.hci_dev = HCI_DEV_NONE; | |
132 | - addr.hci_channel = HCI_CHANNEL_CONTROL; | |
133 | - if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { | |
134 | - ALOGE( "HCI Channel Control: %s", strerror(errno)); | |
135 | - ret = -1; | |
136 | - goto end; | |
137 | - } | |
138 | - | |
139 | - fds[0].fd = fd; | |
140 | - fds[0].events = POLLIN; | |
141 | - | |
142 | - /* Read Controller Index List Command */ | |
143 | - ev.opcode = MGMT_OP_INDEX_LIST; | |
144 | - ev.index = HCI_DEV_NONE; | |
145 | - ev.len = 0; | |
146 | - | |
147 | - ssize_t wrote; | |
148 | - WRITE_NO_INTR(wrote = write(fd, &ev, 6)); | |
149 | - if (wrote != 6) { | |
150 | - ALOGE( "Unable to write mgmt command: %s", strerror(errno)); | |
151 | - ret = -1; | |
152 | - goto end; | |
153 | - } | |
154 | - /* validate mentioned hci interface is present and registered with sock system */ | |
155 | - while (1) { | |
156 | - int n; | |
157 | - WRITE_NO_INTR(n = poll(fds, 1, MGMT_EV_POLL_TIMEOUT)); | |
158 | - if (n == -1) { | |
159 | - ALOGE( "Poll error: %s", strerror(errno)); | |
160 | - ret = -1; | |
161 | - break; | |
162 | - } else if (n == 0) { | |
163 | - ALOGE( "Timeout, no HCI device detected"); | |
164 | - ret = -1; | |
165 | - break; | |
166 | - } | |
167 | - | |
168 | - if (fds[0].revents & POLLIN) { | |
169 | - WRITE_NO_INTR(n = read(fd, &ev, sizeof(struct mgmt_pkt))); | |
170 | - if (n < 0) { | |
171 | - ALOGE( "Error reading control channel: %s", | |
172 | - strerror(errno)); | |
173 | - ret = -1; | |
174 | - break; | |
175 | - } | |
28 | +namespace implementation { | |
176 | 29 | |
177 | - if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) { | |
178 | - goto end; | |
179 | - } else if (ev.opcode == MGMT_EV_COMMAND_COMP) { | |
180 | - struct mgmt_event_read_index* cc; | |
181 | - int i; | |
182 | - | |
183 | - cc = (struct mgmt_event_read_index*)ev.data; | |
184 | - | |
185 | - if (cc->cc_opcode != MGMT_OP_INDEX_LIST || cc->status != 0) continue; | |
186 | - | |
187 | - for (i = 0; i < cc->num_intf; i++) { | |
188 | - if (cc->index[i] == hci_interface) goto end; | |
189 | - } | |
190 | - } | |
191 | - } | |
192 | - } | |
193 | - | |
194 | -end: | |
195 | - ::close(fd); | |
196 | - return ret; | |
197 | -} | |
198 | - | |
199 | -int BluetoothHci::findRfKill() { | |
200 | - char rfkill_type[64]; | |
201 | - char type[16]; | |
202 | - int fd, size, i; | |
203 | - for(i = 0; rfkill_state_ == NULL; i++) | |
204 | - { | |
205 | - snprintf(rfkill_type, sizeof(rfkill_type), "/sys/class/rfkill/rfkill%d/type", i); | |
206 | - if ((fd = open(rfkill_type, O_RDONLY)) < 0) | |
207 | - { | |
208 | - ALOGE("open(%s) failed: %s (%d)\n", rfkill_type, strerror(errno), errno); | |
209 | - return -1; | |
210 | - } | |
211 | - | |
212 | - size = read(fd, &type, sizeof(type)); | |
213 | - ::close(fd); | |
214 | - | |
215 | - if ((size >= 9) && !memcmp(type, "bluetooth", 9)) | |
216 | - { | |
217 | - ::asprintf(&rfkill_state_, "/sys/class/rfkill/rfkill%d/state", i); | |
218 | - break; | |
219 | - } | |
220 | - } | |
221 | - return 0; | |
222 | -} | |
223 | - | |
224 | -int BluetoothHci::rfKill(int block) { | |
225 | - int fd; | |
226 | - char on = (block)?'1':'0'; | |
227 | - if (findRfKill() != 0) return 0; | |
228 | - | |
229 | - fd = open(rfkill_state_, O_WRONLY); | |
230 | - if (fd < 0) { | |
231 | - ALOGE( "Unable to open /dev/rfkill"); | |
232 | - return -1; | |
233 | - } | |
234 | - ssize_t len; | |
235 | - WRITE_NO_INTR(len = write(fd, &on, 1)); | |
236 | - if (len < 0) { | |
237 | - ALOGE( "Failed to change rfkill state"); | |
238 | - ::close(fd); | |
239 | - return -1; | |
240 | - } | |
241 | - ::close(fd); | |
242 | - return 0; | |
243 | -} | |
30 | +static const uint8_t HCI_DATA_TYPE_COMMAND = 1; | |
31 | +static const uint8_t HCI_DATA_TYPE_ACL = 2; | |
32 | +static const uint8_t HCI_DATA_TYPE_SCO = 3; | |
244 | 33 | |
245 | 34 | class BluetoothDeathRecipient : public hidl_death_recipient { |
246 | 35 | public: |
@@ -274,21 +63,39 @@ Return<void> BluetoothHci::initialize( | ||
274 | 63 | |
275 | 64 | death_recipient_->setHasDied(false); |
276 | 65 | cb->linkToDeath(death_recipient_, 0); |
277 | - int hci_fd = openBtHci(); | |
278 | - auto hidl_status = cb->initializationComplete( | |
279 | - hci_fd > 0 ? Status::SUCCESS : Status::INITIALIZATION_ERROR); | |
280 | - if (!hidl_status.isOk()) { | |
66 | + | |
67 | + bool rc = VendorInterface::Initialize( | |
68 | + [cb](bool status) { | |
69 | + auto hidl_status = cb->initializationComplete( | |
70 | + status ? Status::SUCCESS : Status::INITIALIZATION_ERROR); | |
71 | + if (!hidl_status.isOk()) { | |
72 | + ALOGE("VendorInterface -> Unable to call initializationComplete()"); | |
73 | + } | |
74 | + }, | |
75 | + [cb](const hidl_vec<uint8_t>& packet) { | |
76 | + auto hidl_status = cb->hciEventReceived(packet); | |
77 | + if (!hidl_status.isOk()) { | |
78 | + ALOGE("VendorInterface -> Unable to call hciEventReceived()"); | |
79 | + } | |
80 | + }, | |
81 | + [cb](const hidl_vec<uint8_t>& packet) { | |
82 | + auto hidl_status = cb->aclDataReceived(packet); | |
83 | + if (!hidl_status.isOk()) { | |
84 | + ALOGE("VendorInterface -> Unable to call aclDataReceived()"); | |
85 | + } | |
86 | + }, | |
87 | + [cb](const hidl_vec<uint8_t>& packet) { | |
88 | + auto hidl_status = cb->scoDataReceived(packet); | |
89 | + if (!hidl_status.isOk()) { | |
90 | + ALOGE("VendorInterface -> Unable to call scoDataReceived()"); | |
91 | + } | |
92 | + }); | |
93 | + if (!rc) { | |
94 | + auto hidl_status = cb->initializationComplete(Status::INITIALIZATION_ERROR); | |
95 | + if (!hidl_status.isOk()) { | |
281 | 96 | ALOGE("VendorInterface -> Unable to call initializationComplete(ERR)"); |
97 | + } | |
282 | 98 | } |
283 | - hci::H4Protocol* h4_hci = new hci::H4Protocol( | |
284 | - hci_fd, | |
285 | - [cb](const hidl_vec<uint8_t>& packet) { cb->hciEventReceived(packet); }, | |
286 | - [cb](const hidl_vec<uint8_t>& packet) { cb->aclDataReceived(packet); }, | |
287 | - [cb](const hidl_vec<uint8_t>& packet) { cb->scoDataReceived(packet); }); | |
288 | - | |
289 | - fd_watcher_.WatchFdForNonBlockingReads( | |
290 | - hci_fd, [h4_hci](int fd) { h4_hci->OnDataReady(fd); }); | |
291 | - hci_handle_ = h4_hci; | |
292 | 99 | |
293 | 100 | unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) { |
294 | 101 | if (death_recipient->getHasDied()) |
@@ -303,13 +110,7 @@ Return<void> BluetoothHci::initialize( | ||
303 | 110 | Return<void> BluetoothHci::close() { |
304 | 111 | ALOGI("BluetoothHci::close()"); |
305 | 112 | unlink_cb_(death_recipient_); |
306 | - fd_watcher_.StopWatchingFileDescriptors(); | |
307 | - | |
308 | - if (hci_handle_ != nullptr) { | |
309 | - delete hci_handle_; | |
310 | - hci_handle_ = nullptr; | |
311 | - } | |
312 | - closeBtHci(); | |
113 | + VendorInterface::Shutdown(); | |
313 | 114 | return Void(); |
314 | 115 | } |
315 | 116 |
@@ -330,14 +131,14 @@ Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& data) { | ||
330 | 131 | |
331 | 132 | void BluetoothHci::sendDataToController(const uint8_t type, |
332 | 133 | const hidl_vec<uint8_t>& data) { |
333 | - hci_handle_->Send(type, data.data(), data.size()); | |
134 | + VendorInterface::get()->Send(type, data.data(), data.size()); | |
334 | 135 | } |
335 | 136 | |
336 | 137 | IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* /* name */) { |
337 | 138 | return new BluetoothHci(); |
338 | 139 | } |
339 | 140 | |
340 | -} // namespace btlinux | |
141 | +} // namespace implementation | |
341 | 142 | } // namespace V1_0 |
342 | 143 | } // namespace bluetooth |
343 | 144 | } // namespace hardware |
@@ -21,15 +21,13 @@ | ||
21 | 21 | |
22 | 22 | #include <hidl/MQDescriptor.h> |
23 | 23 | |
24 | -#include "async_fd_watcher.h" | |
25 | -#include "h4_protocol.h" | |
26 | -#include "hci_internals.h" | |
24 | +#include <functional> | |
27 | 25 | |
28 | 26 | namespace android { |
29 | 27 | namespace hardware { |
30 | 28 | namespace bluetooth { |
31 | 29 | namespace V1_0 { |
32 | -namespace btlinux { | |
30 | +namespace implementation { | |
33 | 31 | |
34 | 32 | using ::android::hardware::Return; |
35 | 33 | using ::android::hardware::hidl_vec; |
@@ -47,21 +45,6 @@ class BluetoothHci : public IBluetoothHci { | ||
47 | 45 | Return<void> close() override; |
48 | 46 | |
49 | 47 | private: |
50 | - async::AsyncFdWatcher fd_watcher_; | |
51 | - hci::H4Protocol* hci_handle_; | |
52 | - int bt_soc_fd_; | |
53 | - char *rfkill_state_; | |
54 | - | |
55 | - const uint8_t HCI_DATA_TYPE_COMMAND = 1; | |
56 | - const uint8_t HCI_DATA_TYPE_ACL = 2; | |
57 | - const uint8_t HCI_DATA_TYPE_SCO = 3; | |
58 | - | |
59 | - int waitHciDev(int hci_interface); | |
60 | - int findRfKill(void); | |
61 | - int rfKill(int block); | |
62 | - int openBtHci(void); | |
63 | - void closeBtHci(void); | |
64 | - | |
65 | 48 | void sendDataToController(const uint8_t type, const hidl_vec<uint8_t>& data); |
66 | 49 | ::android::sp<BluetoothDeathRecipient> death_recipient_; |
67 | 50 | std::function<void(sp<BluetoothDeathRecipient>&)> unlink_cb_; |
@@ -69,7 +52,7 @@ class BluetoothHci : public IBluetoothHci { | ||
69 | 52 | |
70 | 53 | extern "C" IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* name); |
71 | 54 | |
72 | -} // namespace btlinux | |
55 | +} // namespace implementation | |
73 | 56 | } // namespace V1_0 |
74 | 57 | } // namespace bluetooth |
75 | 58 | } // namespace hardware |
@@ -0,0 +1,435 @@ | ||
1 | +/****************************************************************************** | |
2 | + * | |
3 | + * Copyright (C) 2009-2012 Broadcom 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 implied. | |
14 | + * See the License for the specific language governing permissions and | |
15 | + * limitations under the License. | |
16 | + * | |
17 | + ******************************************************************************/ | |
18 | + | |
19 | +#ifndef BT_VENDOR_LIB_H | |
20 | +#define BT_VENDOR_LIB_H | |
21 | + | |
22 | +#include <stdint.h> | |
23 | +#include <sys/cdefs.h> | |
24 | +#include <sys/types.h> | |
25 | + | |
26 | +#ifdef __cplusplus | |
27 | +extern "C" { | |
28 | +#endif | |
29 | + | |
30 | +/** Struct types */ | |
31 | + | |
32 | +/** Typedefs and defines */ | |
33 | + | |
34 | +/** Vendor specific operations OPCODE */ | |
35 | +typedef enum { | |
36 | + /* [operation] | |
37 | + * Power on or off the BT Controller. | |
38 | + * [input param] | |
39 | + * A pointer to int type with content of bt_vendor_power_state_t. | |
40 | + * Typecasting conversion: (int *) param. | |
41 | + * [return] | |
42 | + * 0 - default, don't care. | |
43 | + * [callback] | |
44 | + * None. | |
45 | + */ | |
46 | + BT_VND_OP_POWER_CTRL, | |
47 | + | |
48 | + /* [operation] | |
49 | + * Perform any vendor specific initialization or configuration | |
50 | + * on the BT Controller. This is called before stack initialization. | |
51 | + * [input param] | |
52 | + * None. | |
53 | + * [return] | |
54 | + * 0 - default, don't care. | |
55 | + * [callback] | |
56 | + * Must call fwcfg_cb to notify the stack of the completion of vendor | |
57 | + * specific initialization once it has been done. | |
58 | + */ | |
59 | + BT_VND_OP_FW_CFG, | |
60 | + | |
61 | + /* [operation] | |
62 | + * Perform any vendor specific SCO/PCM configuration on the BT | |
63 | + * Controller. | |
64 | + * This is called after stack initialization. | |
65 | + * [input param] | |
66 | + * None. | |
67 | + * [return] | |
68 | + * 0 - default, don't care. | |
69 | + * [callback] | |
70 | + * Must call scocfg_cb to notify the stack of the completion of vendor | |
71 | + * specific SCO configuration once it has been done. | |
72 | + */ | |
73 | + BT_VND_OP_SCO_CFG, | |
74 | + | |
75 | + /* [operation] | |
76 | + * Open UART port on where the BT Controller is attached. | |
77 | + * This is called before stack initialization. | |
78 | + * [input param] | |
79 | + * A pointer to int array type for open file descriptors. | |
80 | + * The mapping of HCI channel to fd slot in the int array is given in | |
81 | + * bt_vendor_hci_channels_t. | |
82 | + * And, it requires the vendor lib to fill up the content before | |
83 | + * returning | |
84 | + * the call. | |
85 | + * Typecasting conversion: (int (*)[]) param. | |
86 | + * [return] | |
87 | + * Numbers of opened file descriptors. | |
88 | + * Valid number: | |
89 | + * 1 - CMD/EVT/ACL-In/ACL-Out via the same fd (e.g. UART) | |
90 | + * 2 - CMD/EVT on one fd, and ACL-In/ACL-Out on the other fd | |
91 | + * 4 - CMD, EVT, ACL-In, ACL-Out are on their individual fd | |
92 | + * [callback] | |
93 | + * None. | |
94 | + */ | |
95 | + BT_VND_OP_USERIAL_OPEN, | |
96 | + | |
97 | + /* [operation] | |
98 | + * Close the previously opened UART port. | |
99 | + * [input param] | |
100 | + * None. | |
101 | + * [return] | |
102 | + * 0 - default, don't care. | |
103 | + * [callback] | |
104 | + * None. | |
105 | + */ | |
106 | + BT_VND_OP_USERIAL_CLOSE, | |
107 | + | |
108 | + /* [operation] | |
109 | + * Get the LPM idle timeout in milliseconds. | |
110 | + * The stack uses this information to launch a timer delay before it | |
111 | + * attempts to de-assert LPM WAKE signal once downstream HCI packet | |
112 | + * has been delivered. | |
113 | + * [input param] | |
114 | + * A pointer to uint32_t type which is passed in by the stack. And, it | |
115 | + * requires the vendor lib to fill up the content before returning | |
116 | + * the call. | |
117 | + * Typecasting conversion: (uint32_t *) param. | |
118 | + * [return] | |
119 | + * 0 - default, don't care. | |
120 | + * [callback] | |
121 | + * None. | |
122 | + */ | |
123 | + BT_VND_OP_GET_LPM_IDLE_TIMEOUT, | |
124 | + | |
125 | + /* [operation] | |
126 | + * Enable or disable LPM mode on BT Controller. | |
127 | + * [input param] | |
128 | + * A pointer to uint8_t type with content of bt_vendor_lpm_mode_t. | |
129 | + * Typecasting conversion: (uint8_t *) param. | |
130 | + * [return] | |
131 | + * 0 - default, don't care. | |
132 | + * [callback] | |
133 | + * Must call lpm_cb to notify the stack of the completion of LPM | |
134 | + * disable/enable process once it has been done. | |
135 | + */ | |
136 | + BT_VND_OP_LPM_SET_MODE, | |
137 | + | |
138 | + /* [operation] | |
139 | + * Assert or Deassert LPM WAKE on BT Controller. | |
140 | + * [input param] | |
141 | + * A pointer to uint8_t type with content of bt_vendor_lpm_wake_state_t. | |
142 | + * Typecasting conversion: (uint8_t *) param. | |
143 | + * [return] | |
144 | + * 0 - default, don't care. | |
145 | + * [callback] | |
146 | + * None. | |
147 | + */ | |
148 | + BT_VND_OP_LPM_WAKE_SET_STATE, | |
149 | + | |
150 | + /* [operation] | |
151 | + * Perform any vendor specific commands related to audio state changes. | |
152 | + * [input param] | |
153 | + * a pointer to bt_vendor_op_audio_state_t indicating what audio state is | |
154 | + * set. | |
155 | + * [return] | |
156 | + * 0 - default, don't care. | |
157 | + * [callback] | |
158 | + * None. | |
159 | + */ | |
160 | + BT_VND_OP_SET_AUDIO_STATE, | |
161 | + | |
162 | + /* [operation] | |
163 | + * The epilog call to the vendor module so that it can perform any | |
164 | + * vendor-specific processes (e.g. send a HCI_RESET to BT Controller) | |
165 | + * before the caller calls for cleanup(). | |
166 | + * [input param] | |
167 | + * None. | |
168 | + * [return] | |
169 | + * 0 - default, don't care. | |
170 | + * [callback] | |
171 | + * Must call epilog_cb to notify the stack of the completion of vendor | |
172 | + * specific epilog process once it has been done. | |
173 | + */ | |
174 | + BT_VND_OP_EPILOG, | |
175 | + | |
176 | + /* [operation] | |
177 | + * Call to the vendor module so that it can perform all vendor-specific | |
178 | + * operations to start offloading a2dp media encode & tx. | |
179 | + * [input param] | |
180 | + * pointer to bt_vendor_op_a2dp_offload_start_t containing elements | |
181 | + * required for VND FW to setup a2dp offload. | |
182 | + * [return] | |
183 | + * 0 - default, dont care. | |
184 | + * [callback] | |
185 | + * Must call a2dp_offload_start_cb to notify the stack of the | |
186 | + * completion of vendor specific setup process once it has been done. | |
187 | + */ | |
188 | + BT_VND_OP_A2DP_OFFLOAD_START, | |
189 | + | |
190 | + /* [operation] | |
191 | + * Call to the vendor module so that it can perform all vendor-specific | |
192 | + * operations to suspend offloading a2dp media encode & tx. | |
193 | + * [input param] | |
194 | + * pointer to bt_vendor_op_a2dp_offload_t containing elements | |
195 | + * required for VND FW to setup a2dp offload. | |
196 | + * [return] | |
197 | + * 0 - default, dont care. | |
198 | + * [callback] | |
199 | + * Must call a2dp_offload_cb to notify the stack of the | |
200 | + * completion of vendor specific setup process once it has been done. | |
201 | + */ | |
202 | + BT_VND_OP_A2DP_OFFLOAD_STOP, | |
203 | + | |
204 | +} bt_vendor_opcode_t; | |
205 | + | |
206 | +/** Power on/off control states */ | |
207 | +typedef enum { | |
208 | + BT_VND_PWR_OFF, | |
209 | + BT_VND_PWR_ON, | |
210 | +} bt_vendor_power_state_t; | |
211 | + | |
212 | +/** Define HCI channel identifier in the file descriptors array | |
213 | + used in BT_VND_OP_USERIAL_OPEN operation. | |
214 | + */ | |
215 | +typedef enum { | |
216 | + CH_CMD, // HCI Command channel | |
217 | + CH_EVT, // HCI Event channel | |
218 | + CH_ACL_OUT, // HCI ACL downstream channel | |
219 | + CH_ACL_IN, // HCI ACL upstream channel | |
220 | + | |
221 | + CH_MAX // Total channels | |
222 | +} bt_vendor_hci_channels_t; | |
223 | + | |
224 | +/** LPM disable/enable request */ | |
225 | +typedef enum { | |
226 | + BT_VND_LPM_DISABLE, | |
227 | + BT_VND_LPM_ENABLE, | |
228 | +} bt_vendor_lpm_mode_t; | |
229 | + | |
230 | +/** LPM WAKE set state request */ | |
231 | +typedef enum { | |
232 | + BT_VND_LPM_WAKE_ASSERT, | |
233 | + BT_VND_LPM_WAKE_DEASSERT, | |
234 | +} bt_vendor_lpm_wake_state_t; | |
235 | + | |
236 | +/** Callback result values */ | |
237 | +typedef enum { | |
238 | + BT_VND_OP_RESULT_SUCCESS, | |
239 | + BT_VND_OP_RESULT_FAIL, | |
240 | +} bt_vendor_op_result_t; | |
241 | + | |
242 | +/** audio (SCO) state changes triggering VS commands for configuration */ | |
243 | +typedef struct { | |
244 | + uint16_t handle; | |
245 | + uint16_t peer_codec; | |
246 | + uint16_t state; | |
247 | +} bt_vendor_op_audio_state_t; | |
248 | + | |
249 | +/* | |
250 | + * Bluetooth Host/Controller Vendor callback structure. | |
251 | + */ | |
252 | + | |
253 | +/* vendor initialization/configuration callback */ | |
254 | +typedef void (*cfg_result_cb)(bt_vendor_op_result_t result); | |
255 | + | |
256 | +/* datapath buffer allocation callback (callout) | |
257 | + * | |
258 | + * Vendor lib needs to request a buffer through the alloc callout function | |
259 | + * from HCI lib if the buffer is for constructing a HCI Command packet which | |
260 | + * will be sent through xmit_cb to BT Controller. | |
261 | + * | |
262 | + * For each buffer allocation, the requested size needs to be big enough to | |
263 | + * accommodate the below header plus a complete HCI packet -- | |
264 | + * typedef struct | |
265 | + * { | |
266 | + * uint16_t event; | |
267 | + * uint16_t len; | |
268 | + * uint16_t offset; | |
269 | + * uint16_t layer_specific; | |
270 | + * } HC_BT_HDR; | |
271 | + * | |
272 | + * HCI lib returns a pointer to the buffer where Vendor lib should use to | |
273 | + * construct a HCI command packet as below format: | |
274 | + * | |
275 | + * -------------------------------------------- | |
276 | + * | HC_BT_HDR | HCI command | | |
277 | + * -------------------------------------------- | |
278 | + * where | |
279 | + * HC_BT_HDR.event = 0x2000; | |
280 | + * HC_BT_HDR.len = Length of HCI command; | |
281 | + * HC_BT_HDR.offset = 0; | |
282 | + * HC_BT_HDR.layer_specific = 0; | |
283 | + * | |
284 | + * For example, a HCI_RESET Command will be formed as | |
285 | + * ------------------------ | |
286 | + * | HC_BT_HDR |03|0c|00| | |
287 | + * ------------------------ | |
288 | + * with | |
289 | + * HC_BT_HDR.event = 0x2000; | |
290 | + * HC_BT_HDR.len = 3; | |
291 | + * HC_BT_HDR.offset = 0; | |
292 | + * HC_BT_HDR.layer_specific = 0; | |
293 | + */ | |
294 | +typedef void* (*malloc_cb)(int size); | |
295 | + | |
296 | +/* datapath buffer deallocation callback (callout) */ | |
297 | +typedef void (*mdealloc_cb)(void* p_buf); | |
298 | + | |
299 | +/* define callback of the cmd_xmit_cb | |
300 | + * | |
301 | + * The callback function which HCI lib will call with the return of command | |
302 | + * complete packet. Vendor lib is responsible for releasing the buffer passed | |
303 | + * in at the p_mem parameter by calling dealloc callout function. | |
304 | + */ | |
305 | +typedef void (*tINT_CMD_CBACK)(void* p_mem); | |
306 | + | |
307 | +/* hci command packet transmit callback (callout) | |
308 | + * | |
309 | + * Vendor lib calls xmit_cb callout function in order to send a HCI Command | |
310 | + * packet to BT Controller. The buffer carrying HCI Command packet content | |
311 | + * needs to be first allocated through the alloc callout function. | |
312 | + * HCI lib will release the buffer for Vendor lib once it has delivered the | |
313 | + * packet content to BT Controller. | |
314 | + * | |
315 | + * Vendor lib needs also provide a callback function (p_cback) which HCI lib | |
316 | + * will call with the return of command complete packet. | |
317 | + * | |
318 | + * The opcode parameter gives the HCI OpCode (combination of OGF and OCF) of | |
319 | + * HCI Command packet. For example, opcode = 0x0c03 for the HCI_RESET command | |
320 | + * packet. | |
321 | + */ | |
322 | +typedef uint8_t (*cmd_xmit_cb)(uint16_t opcode, void* p_buf, | |
323 | + tINT_CMD_CBACK p_cback); | |
324 | + | |
325 | +typedef void (*cfg_a2dp_cb)(bt_vendor_op_result_t result, bt_vendor_opcode_t op, | |
326 | + uint8_t bta_av_handle); | |
327 | + | |
328 | +typedef struct { | |
329 | + /** set to sizeof(bt_vendor_callbacks_t) */ | |
330 | + size_t size; | |
331 | + | |
332 | + /* | |
333 | + * Callback and callout functions have implemented in HCI libray | |
334 | + * (libbt-hci.so). | |
335 | + */ | |
336 | + | |
337 | + /* notifies caller result of firmware configuration request */ | |
338 | + cfg_result_cb fwcfg_cb; | |
339 | + | |
340 | + /* notifies caller result of sco configuration request */ | |
341 | + cfg_result_cb scocfg_cb; | |
342 | + | |
343 | + /* notifies caller result of lpm enable/disable */ | |
344 | + cfg_result_cb lpm_cb; | |
345 | + | |
346 | + /* notifies the result of codec setting */ | |
347 | + cfg_result_cb audio_state_cb; | |
348 | + | |
349 | + /* buffer allocation request */ | |
350 | + malloc_cb alloc; | |
351 | + | |
352 | + /* buffer deallocation request */ | |
353 | + mdealloc_cb dealloc; | |
354 | + | |
355 | + /* hci command packet transmit request */ | |
356 | + cmd_xmit_cb xmit_cb; | |
357 | + | |
358 | + /* notifies caller completion of epilog process */ | |
359 | + cfg_result_cb epilog_cb; | |
360 | + | |
361 | + /* notifies status of a2dp offload cmd's */ | |
362 | + cfg_a2dp_cb a2dp_offload_cb; | |
363 | +} bt_vendor_callbacks_t; | |
364 | + | |
365 | +/** A2DP offload request */ | |
366 | +typedef struct { | |
367 | + uint8_t bta_av_handle; /* BTA_AV Handle for callbacks */ | |
368 | + uint16_t xmit_quota; /* Total ACL quota for light stack */ | |
369 | + uint16_t acl_data_size; /* Max ACL data size across HCI transport */ | |
370 | + uint16_t stream_mtu; | |
371 | + uint16_t local_cid; | |
372 | + uint16_t remote_cid; | |
373 | + uint16_t lm_handle; | |
374 | + uint8_t is_flushable; /* true if flushable channel */ | |
375 | + uint32_t stream_source; | |
376 | + uint8_t codec_info[10]; /* Codec capabilities array */ | |
377 | +} bt_vendor_op_a2dp_offload_t; | |
378 | + | |
379 | +/* | |
380 | + * Bluetooth Host/Controller VENDOR Interface | |
381 | + */ | |
382 | +typedef struct { | |
383 | + /** Set to sizeof(bt_vndor_interface_t) */ | |
384 | + size_t size; | |
385 | + | |
386 | + /* | |
387 | + * Functions need to be implemented in Vendor libray (libbt-vendor.so). | |
388 | + */ | |
389 | + | |
390 | + /** | |
391 | + * Caller will open the interface and pass in the callback routines | |
392 | + * to the implemenation of this interface. | |
393 | + */ | |
394 | + int (*init)(const bt_vendor_callbacks_t* p_cb, unsigned char* local_bdaddr); | |
395 | + | |
396 | + /** Vendor specific operations */ | |
397 | + int (*op)(bt_vendor_opcode_t opcode, void* param); | |
398 | + | |
399 | + /** Closes the interface */ | |
400 | + void (*cleanup)(void); | |
401 | +} bt_vendor_interface_t; | |
402 | + | |
403 | +/* | |
404 | + * External shared lib functions/data | |
405 | + */ | |
406 | + | |
407 | +/* Entry point of DLib -- | |
408 | + * Vendor library needs to implement the body of bt_vendor_interface_t | |
409 | + * structure and uses the below name as the variable name. HCI library | |
410 | + * will use this symbol name to get address of the object through the | |
411 | + * dlsym call. | |
412 | + */ | |
413 | +extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE; | |
414 | + | |
415 | +// MODIFICATION FOR NEW HAL/HIDL IMPLEMENTATION: | |
416 | +// EXPOSE THE BT_HDR STRUCT HERE FOR THE VENDOR INTERFACE | |
417 | +// ONLY, WITHOUT REQUIRING INCLUDES FROM system/bt OR OTHER | |
418 | +// DIRECTORIES. | |
419 | +// ONLY USED INSIDE transmit_cb. | |
420 | +// DO NOT USE IN NEW HAL IMPLEMENTATIONS GOING FORWARD | |
421 | +typedef struct | |
422 | +{ | |
423 | + uint16_t event; | |
424 | + uint16_t len; | |
425 | + uint16_t offset; | |
426 | + uint16_t layer_specific; | |
427 | + uint8_t data[]; | |
428 | +} HC_BT_HDR; | |
429 | +// /MODIFICATION | |
430 | + | |
431 | +#ifdef __cplusplus | |
432 | +} | |
433 | +#endif | |
434 | + | |
435 | +#endif /* BT_VENDOR_LIB_H */ |
@@ -15,13 +15,40 @@ | ||
15 | 15 | // |
16 | 16 | |
17 | 17 | #include "h4_protocol.h" |
18 | +#include "esco_parameters.h" | |
19 | +#include "hcidefs.h" | |
18 | 20 | |
19 | 21 | #define LOG_TAG "android.hardware.bluetooth-hci-h4" |
20 | -#include <android-base/logging.h> | |
21 | -#include <assert.h> | |
22 | + | |
23 | +#include <sys/ioctl.h> | |
24 | +#include <linux/usbdevice_fs.h> | |
25 | +#include <asm/byteorder.h> | |
26 | +#include <linux/usb/ch9.h> | |
27 | +#include <libusb/libusb.h> | |
28 | + | |
29 | +typedef uint8_t UINT8; | |
30 | +typedef uint16_t UINT16; | |
31 | + | |
32 | +#define UINT16_TO_STREAM(p, u16) {*(p)++ = (UINT8)(u16); *(p)++ = (UINT8)((u16) >> 8);} | |
33 | +#define UINT8_TO_STREAM(p, u8) {*(p)++ = (UINT8)(u8);} | |
34 | +#define STREAM_TO_UINT8(u8, p) {u8 = (UINT8)(*(p)); (p) += 1;} | |
35 | +#define STREAM_TO_UINT16(u16, p) {u16 = ((UINT16)(*(p)) + (((UINT16)(*((p) + 1))) << 8)); (p) += 2;} | |
36 | + | |
37 | +#define T2_MAXIMUM_LATENCY 0x000D | |
38 | +#define HCIC_PARAM_SIZE_ENH_ACC_ESCO_CONN 63 | |
39 | + | |
40 | +#define INTEL_VID 0x8087 | |
41 | +#define INTEL_PID_8265 0x0a2b // Windstorm peak | |
42 | +#define INTEL_PID_3168 0x0aa7 //SandyPeak (SdP) | |
43 | +#define INTEL_PID_9260 0x0025 // 9160/9260 (also known as ThunderPeak) | |
44 | +#define INTEL_PID_9560 0x0aaa // 9460/9560 also know as Jefferson Peak (JfP) | |
45 | + | |
46 | +#include <errno.h> | |
22 | 47 | #include <fcntl.h> |
48 | +#include <log/log.h> | |
23 | 49 | #include <sys/uio.h> |
24 | -#include <utils/Log.h> | |
50 | +#include <unistd.h> | |
51 | +#include <string.h> | |
25 | 52 | |
26 | 53 | namespace android { |
27 | 54 | namespace hardware { |
@@ -39,6 +66,68 @@ size_t H4Protocol::Send(uint8_t type, const uint8_t* data, size_t length) { | ||
39 | 66 | iov[0].iov_len = sizeof(type); |
40 | 67 | iov[1].iov_base = (void *)data; |
41 | 68 | iov[1].iov_len = length; |
69 | + | |
70 | + if (type == HCI_PACKET_TYPE_COMMAND) { | |
71 | + uint8_t* p; | |
72 | + void* r; | |
73 | + uint8_t* q; | |
74 | + uint16_t command; | |
75 | + uint8_t coding_format; | |
76 | + /* Marvell specific Configuration */ | |
77 | + const uint16_t input_coded_data_size = 8; | |
78 | + const uint16_t output_coded_data_size = 8; | |
79 | + const uint8_t input_transport_unit_size = 16; | |
80 | + const uint8_t output_transport_unit_size = 16; | |
81 | + const uint8_t packet_size = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_ENH_ACC_ESCO_CONN; | |
82 | + const uint16_t max_latency_ms = 13; | |
83 | + | |
84 | + p = (uint8_t*)data; | |
85 | + STREAM_TO_UINT16(command, p); | |
86 | + p += 15; // Increment stream pinter to point coding format byte | |
87 | + STREAM_TO_UINT8(coding_format, p); | |
88 | + | |
89 | + if ((command == HCI_ENH_ACCEPT_ESCO_CONNECTION) && | |
90 | + (coding_format == ESCO_CODING_FORMAT_MSBC)) { | |
91 | + ALOGV("%s accept esco", __func__); | |
92 | + q = (uint8_t*)malloc(packet_size); | |
93 | + | |
94 | + if (q == NULL) { | |
95 | + ALOGE("%s Memory allocation for SCO config parameters failed", __func__); | |
96 | + } else { | |
97 | + r = q; | |
98 | + memcpy(q, data, packet_size); | |
99 | + q += 49; // Increment stream pointer to point to input_coded_data_size | |
100 | + UINT16_TO_STREAM(q, input_coded_data_size); | |
101 | + UINT16_TO_STREAM(q, output_coded_data_size); | |
102 | + q += 6; // Increment stream pointer to point to input_transport_unit_size | |
103 | + UINT8_TO_STREAM(q, input_transport_unit_size); | |
104 | + UINT8_TO_STREAM(q, output_transport_unit_size); | |
105 | + UINT16_TO_STREAM(q, max_latency_ms); | |
106 | + /* Write T2 specific Settings */ | |
107 | + UINT16_TO_STREAM(q, (ESCO_PKT_TYPES_MASK_EV3 | ESCO_PKT_TYPES_MASK_NO_3_EV3 | | |
108 | + ESCO_PKT_TYPES_MASK_NO_2_EV5 | ESCO_PKT_TYPES_MASK_NO_3_EV5)); | |
109 | + | |
110 | + iov[1].iov_base = r; | |
111 | + } | |
112 | + while (1) { | |
113 | + ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, 2)); | |
114 | + if (ret == -1) { | |
115 | + if (errno == EAGAIN) { | |
116 | + ALOGE("%s error writing to UART (%s)", __func__, strerror(errno)); | |
117 | + continue; | |
118 | + } | |
119 | + } else if (ret == 0) { | |
120 | + ALOGE("%s zero bytes written - something went wrong...", __func__); | |
121 | + break; | |
122 | + } | |
123 | + break; | |
124 | + } | |
125 | + free (q); | |
126 | + return ret; | |
127 | + } | |
128 | + } | |
129 | + | |
130 | + ALOGV("%x %x %x", data[0],data[1],data[2]); | |
42 | 131 | while (1) { |
43 | 132 | ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, 2)); |
44 | 133 | if (ret == -1) { |
@@ -47,7 +136,6 @@ size_t H4Protocol::Send(uint8_t type, const uint8_t* data, size_t length) { | ||
47 | 136 | continue; |
48 | 137 | } |
49 | 138 | } else if (ret == 0) { |
50 | - // Nothing written :( | |
51 | 139 | ALOGE("%s zero bytes written - something went wrong...", __func__); |
52 | 140 | break; |
53 | 141 | } |
@@ -56,9 +144,97 @@ size_t H4Protocol::Send(uint8_t type, const uint8_t* data, size_t length) { | ||
56 | 144 | return ret; |
57 | 145 | } |
58 | 146 | |
147 | +bool H4Protocol::IsIntelController(uint16_t vid, uint16_t pid) { | |
148 | + if ((vid == INTEL_VID) && ((pid == INTEL_PID_8265) || | |
149 | + (pid == INTEL_PID_3168)|| | |
150 | + (pid == INTEL_PID_9260)|| | |
151 | + (pid == INTEL_PID_9560))) | |
152 | + return true; | |
153 | + else | |
154 | + return false; | |
155 | +} | |
156 | + | |
157 | +void H4Protocol::GetUsbpath(void) { | |
158 | + size_t count, i; | |
159 | + int ret, busnum, devnum; | |
160 | + struct libusb_device **dev_list = NULL; | |
161 | + struct libusb_context *ctx; | |
162 | + uint16_t vid = 0, pid = 0; | |
163 | + ALOGD(" Initializing GenericUSB (libusb-1.0)...\n"); | |
164 | + ret = libusb_init(&ctx); | |
165 | + if (ret < 0) { | |
166 | + ALOGE("libusb failed to initialize: %d\n", ret); | |
167 | + return; | |
168 | + } | |
169 | + count = libusb_get_device_list(ctx, &dev_list); | |
170 | + if (count <= 0) { | |
171 | + ALOGE("Error getting USB device list: %s\n", strerror(count)); | |
172 | + libusb_exit(ctx); | |
173 | + return; | |
174 | + } | |
175 | + for (i = 0; i < count; ++i) { | |
176 | + struct libusb_device* dev = dev_list[i]; | |
177 | + busnum = libusb_get_bus_number(dev); | |
178 | + devnum = libusb_get_device_address(dev); | |
179 | + struct libusb_device_descriptor descriptor; | |
180 | + ret = libusb_get_device_descriptor(dev, &descriptor); | |
181 | + if (ret < 0) { | |
182 | + ALOGE("Error getting device descriptor %d ", ret); | |
183 | + goto exit; | |
184 | + } | |
185 | + vid = descriptor.idVendor; | |
186 | + pid = descriptor.idProduct; | |
187 | + if (H4Protocol::IsIntelController(vid, pid)) { | |
188 | + snprintf(dev_address, sizeof(dev_address), "/dev/bus/usb/%03d/%03d", | |
189 | + busnum, devnum); | |
190 | + ALOGV("Value of BT device address = %s", dev_address); | |
191 | + goto exit; | |
192 | + } | |
193 | + } | |
194 | +exit: | |
195 | + libusb_free_device_list(dev_list, count); | |
196 | + libusb_exit(ctx); | |
197 | +} | |
198 | + | |
199 | +void H4Protocol::SendHandle(void) { | |
200 | + int fd,ret; | |
201 | + fd = open(dev_address,O_WRONLY|O_NONBLOCK); | |
202 | + if (fd < 0) { | |
203 | + ALOGE("Fail to open USB device %s, value of fd= %d", dev_address, fd); | |
204 | + } else { | |
205 | + struct usbdevfs_ioctl wrapper; | |
206 | + wrapper.ifno = 1; | |
207 | + wrapper.ioctl_code = USBDEVFS_IOCTL; | |
208 | + wrapper.data = sco_handle; | |
209 | + ret = ioctl(fd, USBDEVFS_IOCTL, &wrapper); | |
210 | + if (ret < 0) | |
211 | + ALOGE("Failed to send SCO handle err = %d", ret); | |
212 | + close(fd); | |
213 | + } | |
214 | +} | |
215 | + | |
59 | 216 | void H4Protocol::OnPacketReady() { |
60 | 217 | switch (hci_packet_type_) { |
61 | 218 | case HCI_PACKET_TYPE_EVENT: |
219 | + if ((hci_packetizer_.GetPacket())[0] == HCI_COMMAND_COMPLETE_EVT) { | |
220 | + unsigned int cmd, lsb, msb; | |
221 | + msb = hci_packetizer_.GetPacket()[4] ; | |
222 | + lsb = hci_packetizer_.GetPacket()[3]; | |
223 | + cmd = msb << 8 | lsb ; | |
224 | + | |
225 | + if (cmd == HCI_RESET) { | |
226 | + event_cb_(hci_packetizer_.GetPacket()); | |
227 | + hci_packet_type_ = HCI_PACKET_TYPE_UNKNOWN; | |
228 | + H4Protocol::GetUsbpath(); | |
229 | + return; | |
230 | + } | |
231 | + } else if ((hci_packetizer_.GetPacket())[0] == HCI_ESCO_CONNECTION_COMP_EVT) { | |
232 | + const unsigned char *handle = hci_packetizer_.GetPacket().data() + 3; | |
233 | + memcpy(sco_handle, handle, 2); | |
234 | + ALOGI("Value of SCO handle = %x, %x", handle[0], handle[1]); | |
235 | + H4Protocol::SendHandle(); | |
236 | + } | |
237 | + | |
62 | 238 | event_cb_(hci_packetizer_.GetPacket()); |
63 | 239 | break; |
64 | 240 | case HCI_PACKET_TYPE_ACL_DATA: |
@@ -67,18 +243,27 @@ void H4Protocol::OnPacketReady() { | ||
67 | 243 | case HCI_PACKET_TYPE_SCO_DATA: |
68 | 244 | sco_cb_(hci_packetizer_.GetPacket()); |
69 | 245 | break; |
70 | - default: { | |
71 | - bool bad_packet_type = true; | |
72 | - CHECK(!bad_packet_type); | |
73 | - } | |
246 | + default: | |
247 | + LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__, | |
248 | + static_cast<int>(hci_packet_type_)); | |
74 | 249 | } |
75 | 250 | // Get ready for the next type byte. |
76 | 251 | hci_packet_type_ = HCI_PACKET_TYPE_UNKNOWN; |
77 | 252 | } |
78 | 253 | |
254 | + | |
255 | +typedef struct | |
256 | +{ | |
257 | + uint8_t type; | |
258 | + uint8_t event; | |
259 | + uint8_t len; | |
260 | + uint8_t offset; | |
261 | + uint16_t layer_specific; | |
262 | +} BT_EVENT_HDR; | |
263 | + | |
79 | 264 | void H4Protocol::OnDataReady(int fd) { |
80 | 265 | if (hci_packet_type_ == HCI_PACKET_TYPE_UNKNOWN) { |
81 | - /** | |
266 | + /* | |
82 | 267 | * read full buffer. ACL max length is 2 bytes, and SCO max length is 2 |
83 | 268 | * byte. so taking 64K as buffer length. |
84 | 269 | * Question : Why to read in single chunk rather than multiple reads, |
@@ -94,9 +279,39 @@ void H4Protocol::OnDataReady(int fd) { | ||
94 | 279 | const size_t max_plen = 64*1024; |
95 | 280 | hidl_vec<uint8_t> tpkt; |
96 | 281 | tpkt.resize(max_plen); |
97 | - size_t bytes_read = TEMP_FAILURE_RETRY(read(fd, tpkt.data(), max_plen)); | |
282 | + ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, tpkt.data(), max_plen)); | |
283 | + if (bytes_read == 0) { | |
284 | + // This is only expected if the UART got closed when shutting down. | |
285 | + ALOGE("%s: Unexpected EOF reading the packet type!", __func__); | |
286 | + sleep(5); // Expect to be shut down within 5 seconds. | |
287 | + return; | |
288 | + } else if (bytes_read < 0) { | |
289 | + LOG_ALWAYS_FATAL("%s: Read packet type error: %s", __func__, | |
290 | + strerror(errno)); | |
291 | + } | |
98 | 292 | hci_packet_type_ = static_cast<HciPacketType>(tpkt.data()[0]); |
99 | - hci_packetizer_.CbHciPacket(tpkt.data()+1, bytes_read-1); | |
293 | + if (hci_packet_type_ != HCI_PACKET_TYPE_ACL_DATA && | |
294 | + hci_packet_type_ != HCI_PACKET_TYPE_SCO_DATA && | |
295 | + hci_packet_type_ != HCI_PACKET_TYPE_EVENT) { | |
296 | + LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__, | |
297 | + static_cast<int>(hci_packet_type_)); | |
298 | + } else { | |
299 | + if (tpkt.data()[1] == HCI_COMMAND_COMPLETE_EVT) { | |
300 | + ALOGD("%s Command complete event ncmds = %d", | |
301 | + __func__, tpkt.data()[3]); | |
302 | + tpkt.data()[3] = 1; | |
303 | + /* Disable Enhance setup synchronous connections*/ | |
304 | + BT_EVENT_HDR* hdr = (BT_EVENT_HDR*)(tpkt.data()); | |
305 | + if (hdr->layer_specific == HCI_READ_LOCAL_SUPPORTED_CMDS) | |
306 | + tpkt.data()[36] &= ~((uint8_t)0x1 << 3); | |
307 | + | |
308 | + } else if (tpkt.data()[1] == HCI_COMMAND_STATUS_EVT) { | |
309 | + ALOGV("%s Command status event ncmd = %d", __func__, tpkt.data()[4]); | |
310 | + tpkt.data()[4] = 1; | |
311 | + } | |
312 | + | |
313 | + hci_packetizer_.CbHciPacket(tpkt.data() + 1, bytes_read - 1); | |
314 | + } | |
100 | 315 | } |
101 | 316 | } |
102 | 317 |
@@ -19,18 +19,16 @@ | ||
19 | 19 | #include <hidl/HidlSupport.h> |
20 | 20 | |
21 | 21 | #include "async_fd_watcher.h" |
22 | +#include "bt_vendor_lib.h" | |
22 | 23 | #include "hci_internals.h" |
23 | -#include "hci_packetizer.h" | |
24 | +#include "hci_protocol.h" | |
24 | 25 | |
25 | 26 | namespace android { |
26 | 27 | namespace hardware { |
27 | 28 | namespace bluetooth { |
28 | 29 | namespace hci { |
29 | 30 | |
30 | -using ::android::hardware::hidl_vec; | |
31 | -using PacketReadCallback = std::function<void(const hidl_vec<uint8_t>&)>; | |
32 | - | |
33 | -class H4Protocol { | |
31 | +class H4Protocol : public HciProtocol { | |
34 | 32 | public: |
35 | 33 | H4Protocol(int fd, PacketReadCallback event_cb, PacketReadCallback acl_cb, |
36 | 34 | PacketReadCallback sco_cb) |
@@ -46,15 +44,25 @@ class H4Protocol { | ||
46 | 44 | |
47 | 45 | void OnDataReady(int fd); |
48 | 46 | |
47 | + bool IsIntelController(uint16_t vid, uint16_t pid); | |
48 | + | |
49 | + void GetUsbpath(void); | |
50 | + | |
51 | + void SendHandle(void); | |
52 | + | |
49 | 53 | private: |
50 | 54 | int uart_fd_; |
51 | 55 | |
56 | + uint8_t sco_handle[2]; | |
57 | + | |
58 | + char dev_address[32]; | |
59 | + | |
52 | 60 | PacketReadCallback event_cb_; |
53 | 61 | PacketReadCallback acl_cb_; |
54 | 62 | PacketReadCallback sco_cb_; |
55 | 63 | |
56 | 64 | HciPacketType hci_packet_type_{HCI_PACKET_TYPE_UNKNOWN}; |
57 | - HciPacketizer hci_packetizer_; | |
65 | + hci::HciPacketizer hci_packetizer_; | |
58 | 66 | }; |
59 | 67 | |
60 | 68 | } // namespace hci |
@@ -17,11 +17,12 @@ | ||
17 | 17 | #include "hci_packetizer.h" |
18 | 18 | |
19 | 19 | #define LOG_TAG "android.hardware.bluetooth.hci_packetizer" |
20 | -#include <android-base/logging.h> | |
21 | -#include <utils/Log.h> | |
22 | 20 | |
23 | 21 | #include <dlfcn.h> |
22 | +#include <errno.h> | |
24 | 23 | #include <fcntl.h> |
24 | +#include <unistd.h> | |
25 | +#include <utils/Log.h> | |
25 | 26 | |
26 | 27 | namespace { |
27 | 28 |
@@ -45,21 +46,31 @@ namespace hardware { | ||
45 | 46 | namespace bluetooth { |
46 | 47 | namespace hci { |
47 | 48 | |
48 | -const hidl_vec<uint8_t>& HciPacketizer::GetPacket() const { return packet_; } | |
49 | +const hidl_vec<uint8_t>& HciPacketizer::GetPacket() const { | |
50 | + return packet_; | |
51 | +} | |
49 | 52 | |
50 | 53 | void HciPacketizer::CbHciPacket(uint8_t *data, size_t len) { |
51 | 54 | packet_.setToExternal(data, len); |
52 | 55 | packet_ready_cb_(); |
53 | 56 | } |
54 | 57 | |
55 | -#if 0 | |
56 | 58 | void HciPacketizer::OnDataReady(int fd, HciPacketType packet_type) { |
57 | 59 | switch (state_) { |
58 | 60 | case HCI_PREAMBLE: { |
59 | - size_t bytes_read = TEMP_FAILURE_RETRY( | |
61 | + ssize_t bytes_read = TEMP_FAILURE_RETRY( | |
60 | 62 | read(fd, preamble_ + bytes_read_, |
61 | 63 | preamble_size_for_type[packet_type] - bytes_read_)); |
62 | - CHECK(bytes_read > 0); | |
64 | + if (bytes_read == 0) { | |
65 | + // This is only expected if the UART got closed when shutting down. | |
66 | + ALOGE("%s: Unexpected EOF reading the header!", __func__); | |
67 | + sleep(5); // Expect to be shut down within 5 seconds. | |
68 | + return; | |
69 | + } | |
70 | + if (bytes_read < 0) { | |
71 | + LOG_ALWAYS_FATAL("%s: Read header error: %s", __func__, | |
72 | + strerror(errno)); | |
73 | + } | |
63 | 74 | bytes_read_ += bytes_read; |
64 | 75 | if (bytes_read_ == preamble_size_for_type[packet_type]) { |
65 | 76 | size_t packet_length = |
@@ -74,11 +85,20 @@ void HciPacketizer::OnDataReady(int fd, HciPacketType packet_type) { | ||
74 | 85 | } |
75 | 86 | |
76 | 87 | case HCI_PAYLOAD: { |
77 | - size_t bytes_read = TEMP_FAILURE_RETRY(read( | |
88 | + ssize_t bytes_read = TEMP_FAILURE_RETRY(read( | |
78 | 89 | fd, |
79 | 90 | packet_.data() + preamble_size_for_type[packet_type] + bytes_read_, |
80 | 91 | bytes_remaining_)); |
81 | - CHECK(bytes_read > 0); | |
92 | + if (bytes_read == 0) { | |
93 | + // This is only expected if the UART got closed when shutting down. | |
94 | + ALOGE("%s: Unexpected EOF reading the payload!", __func__); | |
95 | + sleep(5); // Expect to be shut down within 5 seconds. | |
96 | + return; | |
97 | + } | |
98 | + if (bytes_read < 0) { | |
99 | + LOG_ALWAYS_FATAL("%s: Read payload error: %s", __func__, | |
100 | + strerror(errno)); | |
101 | + } | |
82 | 102 | bytes_remaining_ -= bytes_read; |
83 | 103 | bytes_read_ += bytes_read; |
84 | 104 | if (bytes_remaining_ == 0) { |
@@ -90,7 +110,6 @@ void HciPacketizer::OnDataReady(int fd, HciPacketType packet_type) { | ||
90 | 110 | } |
91 | 111 | } |
92 | 112 | } |
93 | -#endif | |
94 | 113 | |
95 | 114 | } // namespace hci |
96 | 115 | } // namespace bluetooth |
@@ -0,0 +1,58 @@ | ||
1 | +// | |
2 | +// Copyright 2017 The Android Open Source Project | |
3 | +// | |
4 | +// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +// you may not use this file except in compliance with the License. | |
6 | +// You may obtain a copy of the License at | |
7 | +// | |
8 | +// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +// | |
10 | +// Unless required by applicable law or agreed to in writing, software | |
11 | +// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +// See the License for the specific language governing permissions and | |
14 | +// limitations under the License. | |
15 | +// | |
16 | + | |
17 | +#include "hci_protocol.h" | |
18 | + | |
19 | +#define LOG_TAG "android.hardware.bluetooth-hci-hci_protocol" | |
20 | +#include <assert.h> | |
21 | +#include <errno.h> | |
22 | +#include <fcntl.h> | |
23 | +#include <unistd.h> | |
24 | +#include <log/log.h> | |
25 | + | |
26 | +namespace android { | |
27 | +namespace hardware { | |
28 | +namespace bluetooth { | |
29 | +namespace hci { | |
30 | + | |
31 | +size_t HciProtocol::WriteSafely(int fd, const uint8_t* data, size_t length) { | |
32 | + size_t transmitted_length = 0; | |
33 | + while (length > 0) { | |
34 | + ssize_t ret = | |
35 | + TEMP_FAILURE_RETRY(write(fd, data + transmitted_length, length)); | |
36 | + | |
37 | + if (ret == -1) { | |
38 | + if (errno == EAGAIN) continue; | |
39 | + ALOGE("%s error writing to UART (%s)", __func__, strerror(errno)); | |
40 | + break; | |
41 | + | |
42 | + } else if (ret == 0) { | |
43 | + // Nothing written :( | |
44 | + ALOGE("%s zero bytes written - something went wrong...", __func__); | |
45 | + break; | |
46 | + } | |
47 | + | |
48 | + transmitted_length += ret; | |
49 | + length -= ret; | |
50 | + } | |
51 | + | |
52 | + return transmitted_length; | |
53 | +} | |
54 | + | |
55 | +} // namespace hci | |
56 | +} // namespace bluetooth | |
57 | +} // namespace hardware | |
58 | +} // namespace android |
@@ -0,0 +1,49 @@ | ||
1 | +// | |
2 | +// Copyright 2017 The Android Open Source Project | |
3 | +// | |
4 | +// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +// you may not use this file except in compliance with the License. | |
6 | +// You may obtain a copy of the License at | |
7 | +// | |
8 | +// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +// | |
10 | +// Unless required by applicable law or agreed to in writing, software | |
11 | +// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +// See the License for the specific language governing permissions and | |
14 | +// limitations under the License. | |
15 | +// | |
16 | + | |
17 | +#pragma once | |
18 | + | |
19 | +#include <hidl/HidlSupport.h> | |
20 | + | |
21 | +#include "bt_vendor_lib.h" | |
22 | +#include "hci_internals.h" | |
23 | +#include "hci_packetizer.h" | |
24 | + | |
25 | +namespace android { | |
26 | +namespace hardware { | |
27 | +namespace bluetooth { | |
28 | +namespace hci { | |
29 | + | |
30 | +using ::android::hardware::hidl_vec; | |
31 | +using PacketReadCallback = std::function<void(const hidl_vec<uint8_t>&)>; | |
32 | + | |
33 | +// Implementation of HCI protocol bits common to different transports | |
34 | +class HciProtocol { | |
35 | + public: | |
36 | + HciProtocol() = default; | |
37 | + virtual ~HciProtocol(){}; | |
38 | + | |
39 | + // Protocol-specific implementation of sending packets. | |
40 | + virtual size_t Send(uint8_t type, const uint8_t* data, size_t length) = 0; | |
41 | + | |
42 | + protected: | |
43 | + static size_t WriteSafely(int fd, const uint8_t* data, size_t length); | |
44 | +}; | |
45 | + | |
46 | +} // namespace hci | |
47 | +} // namespace bluetooth | |
48 | +} // namespace hardware | |
49 | +} // namespace android |
@@ -0,0 +1,70 @@ | ||
1 | +// | |
2 | +// Copyright 2017 The Android Open Source Project | |
3 | +// | |
4 | +// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +// you may not use this file except in compliance with the License. | |
6 | +// You may obtain a copy of the License at | |
7 | +// | |
8 | +// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +// | |
10 | +// Unless required by applicable law or agreed to in writing, software | |
11 | +// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +// See the License for the specific language governing permissions and | |
14 | +// limitations under the License. | |
15 | +// | |
16 | + | |
17 | +#include "mct_protocol.h" | |
18 | + | |
19 | +#include <assert.h> | |
20 | + | |
21 | +#define LOG_TAG "android.hardware.bluetooth-hci-mct" | |
22 | +#include <utils/Log.h> | |
23 | + | |
24 | +#include <fcntl.h> | |
25 | + | |
26 | +namespace android { | |
27 | +namespace hardware { | |
28 | +namespace bluetooth { | |
29 | +namespace hci { | |
30 | + | |
31 | +MctProtocol::MctProtocol(int* fds, PacketReadCallback event_cb, | |
32 | + PacketReadCallback acl_cb) | |
33 | + : event_cb_(event_cb), | |
34 | + acl_cb_(acl_cb), | |
35 | + event_packetizer_([this]() { OnEventPacketReady(); }), | |
36 | + acl_packetizer_([this]() { OnAclDataPacketReady(); }) { | |
37 | + for (int i = 0; i < CH_MAX; i++) { | |
38 | + uart_fds_[i] = fds[i]; | |
39 | + } | |
40 | +} | |
41 | + | |
42 | +size_t MctProtocol::Send(uint8_t type, const uint8_t* data, size_t length) { | |
43 | + if (type == HCI_PACKET_TYPE_COMMAND) | |
44 | + return WriteSafely(uart_fds_[CH_CMD], data, length); | |
45 | + if (type == HCI_PACKET_TYPE_ACL_DATA) | |
46 | + return WriteSafely(uart_fds_[CH_ACL_OUT], data, length); | |
47 | + LOG_ALWAYS_FATAL("%s: Unimplemented packet type = %d", __func__, type); | |
48 | + return 0; | |
49 | +} | |
50 | + | |
51 | +void MctProtocol::OnEventPacketReady() { | |
52 | + event_cb_(event_packetizer_.GetPacket()); | |
53 | +} | |
54 | + | |
55 | +void MctProtocol::OnAclDataPacketReady() { | |
56 | + acl_cb_(acl_packetizer_.GetPacket()); | |
57 | +} | |
58 | + | |
59 | +void MctProtocol::OnEventDataReady(int fd) { | |
60 | + event_packetizer_.OnDataReady(fd, HCI_PACKET_TYPE_EVENT); | |
61 | +} | |
62 | + | |
63 | +void MctProtocol::OnAclDataReady(int fd) { | |
64 | + acl_packetizer_.OnDataReady(fd, HCI_PACKET_TYPE_ACL_DATA); | |
65 | +} | |
66 | + | |
67 | +} // namespace hci | |
68 | +} // namespace bluetooth | |
69 | +} // namespace hardware | |
70 | +} // namespace android |
@@ -0,0 +1,56 @@ | ||
1 | +// | |
2 | +// Copyright 2017 The Android Open Source Project | |
3 | +// | |
4 | +// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +// you may not use this file except in compliance with the License. | |
6 | +// You may obtain a copy of the License at | |
7 | +// | |
8 | +// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +// | |
10 | +// Unless required by applicable law or agreed to in writing, software | |
11 | +// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +// See the License for the specific language governing permissions and | |
14 | +// limitations under the License. | |
15 | +// | |
16 | + | |
17 | +#pragma once | |
18 | + | |
19 | +#include <hidl/HidlSupport.h> | |
20 | + | |
21 | +#include "async_fd_watcher.h" | |
22 | +#include "bt_vendor_lib.h" | |
23 | +#include "hci_internals.h" | |
24 | +#include "hci_protocol.h" | |
25 | + | |
26 | +namespace android { | |
27 | +namespace hardware { | |
28 | +namespace bluetooth { | |
29 | +namespace hci { | |
30 | + | |
31 | +class MctProtocol : public HciProtocol { | |
32 | + public: | |
33 | + MctProtocol(int* fds, PacketReadCallback event_cb, PacketReadCallback acl_cb); | |
34 | + | |
35 | + size_t Send(uint8_t type, const uint8_t* data, size_t length); | |
36 | + | |
37 | + void OnEventPacketReady(); | |
38 | + void OnAclDataPacketReady(); | |
39 | + | |
40 | + void OnEventDataReady(int fd); | |
41 | + void OnAclDataReady(int fd); | |
42 | + | |
43 | + private: | |
44 | + int uart_fds_[CH_MAX]; | |
45 | + | |
46 | + PacketReadCallback event_cb_; | |
47 | + PacketReadCallback acl_cb_; | |
48 | + | |
49 | + hci::HciPacketizer event_packetizer_; | |
50 | + hci::HciPacketizer acl_packetizer_; | |
51 | +}; | |
52 | + | |
53 | +} // namespace hci | |
54 | +} // namespace bluetooth | |
55 | +} // namespace hardware | |
56 | +} // namespace android |
@@ -1,5 +1,5 @@ | ||
1 | 1 | // |
2 | -// Copyright 2017 The Android Open Source Project | |
2 | +// Copyright 2016 The Android Open Source Project | |
3 | 3 | // |
4 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | // you may not use this file except in compliance with the License. |
@@ -19,22 +19,19 @@ | ||
19 | 19 | #include <android/hardware/bluetooth/1.0/IBluetoothHci.h> |
20 | 20 | #include <hidl/HidlSupport.h> |
21 | 21 | #include <hidl/HidlTransportSupport.h> |
22 | -#include <utils/Log.h> | |
22 | + | |
23 | 23 | |
24 | 24 | #include "bluetooth_hci.h" |
25 | 25 | |
26 | 26 | using ::android::hardware::configureRpcThreadpool; |
27 | 27 | using ::android::hardware::bluetooth::V1_0::IBluetoothHci; |
28 | -using ::android::hardware::bluetooth::V1_0::btlinux::BluetoothHci; | |
28 | +using ::android::hardware::bluetooth::V1_0::implementation::BluetoothHci; | |
29 | 29 | using ::android::hardware::joinRpcThreadpool; |
30 | 30 | using ::android::sp; |
31 | 31 | |
32 | 32 | int main(int /* argc */, char** /* argv */) { |
33 | 33 | sp<IBluetoothHci> bluetooth = new BluetoothHci; |
34 | 34 | configureRpcThreadpool(1, true); |
35 | - android::status_t status = bluetooth->registerAsService(); | |
36 | - if (status == android::OK) | |
37 | - joinRpcThreadpool(); | |
38 | - else | |
39 | - ALOGE("Could not register as a service!"); | |
35 | + bluetooth->registerAsService(); | |
36 | + joinRpcThreadpool(); | |
40 | 37 | } |
@@ -0,0 +1,426 @@ | ||
1 | +// | |
2 | +// Copyright 2016 The Android Open Source Project | |
3 | +// | |
4 | +// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +// you may not use this file except in compliance with the License. | |
6 | +// You may obtain a copy of the License at | |
7 | +// | |
8 | +// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +// | |
10 | +// Unless required by applicable law or agreed to in writing, software | |
11 | +// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +// See the License for the specific language governing permissions and | |
14 | +// limitations under the License. | |
15 | +// | |
16 | + | |
17 | +#include "vendor_interface.h" | |
18 | + | |
19 | +#define LOG_TAG "android.hardware.bluetooth@1.0-service.btlinux" | |
20 | +#include <cutils/properties.h> | |
21 | +#include <utils/Log.h> | |
22 | + | |
23 | +#include <dlfcn.h> | |
24 | +#include <fcntl.h> | |
25 | + | |
26 | +#include "esco_parameters.h" | |
27 | +#include "hcidefs.h" | |
28 | + | |
29 | +#include "bluetooth_address.h" | |
30 | +#include "h4_protocol.h" | |
31 | +#include "mct_protocol.h" | |
32 | + | |
33 | +typedef uint8_t UINT8; | |
34 | +typedef uint16_t UINT16; | |
35 | + | |
36 | +#define STREAM_TO_UINT8(u8, p) {u8 = (UINT8)(*(p)); (p) += 1;} | |
37 | +#define STREAM_TO_UINT16(u16, p) {u16 = ((UINT16)(*(p)) + (((UINT16)(*((p) + 1))) << 8)); (p) += 2;} | |
38 | + | |
39 | +static const char* VENDOR_LIBRARY_NAME = "libbt-vendor.so"; | |
40 | +static const char* VENDOR_LIBRARY_SYMBOL_NAME = | |
41 | + "BLUETOOTH_VENDOR_LIB_INTERFACE"; | |
42 | + | |
43 | +static const int INVALID_FD = -1; | |
44 | + | |
45 | +namespace { | |
46 | + | |
47 | +using android::hardware::bluetooth::V1_0::implementation::VendorInterface; | |
48 | +using android::hardware::hidl_vec; | |
49 | + | |
50 | +struct { | |
51 | + tINT_CMD_CBACK cb; | |
52 | + uint16_t opcode; | |
53 | +} internal_command; | |
54 | + | |
55 | +// True when LPM is not enabled yet or wake is not asserted. | |
56 | +bool lpm_wake_deasserted; | |
57 | +uint32_t lpm_timeout_ms; | |
58 | +bool recent_activity_flag; | |
59 | + | |
60 | +VendorInterface* g_vendor_interface = nullptr; | |
61 | +std::mutex wakeup_mutex_; | |
62 | + | |
63 | +HC_BT_HDR* WrapPacketAndCopy(uint16_t event, const hidl_vec<uint8_t>& data) { | |
64 | + size_t packet_size = data.size() + sizeof(HC_BT_HDR); | |
65 | + HC_BT_HDR* packet = reinterpret_cast<HC_BT_HDR*>(new uint8_t[packet_size]); | |
66 | + packet->offset = 0; | |
67 | + packet->len = data.size(); | |
68 | + packet->layer_specific = 0; | |
69 | + packet->event = event; | |
70 | + // TODO(eisenbach): Avoid copy here; if BT_HDR->data can be ensured to | |
71 | + // be the only way the data is accessed, a pointer could be passed here... | |
72 | + memcpy(packet->data, data.data(), data.size()); | |
73 | + return packet; | |
74 | +} | |
75 | + | |
76 | +bool internal_command_event_match(const hidl_vec<uint8_t>& packet) { | |
77 | + uint8_t event_code = packet[0]; | |
78 | + if (event_code != HCI_COMMAND_COMPLETE_EVENT) { | |
79 | + ALOGE("%s: Unhandled event type %02X", __func__, event_code); | |
80 | + return false; | |
81 | + } | |
82 | + | |
83 | + size_t opcode_offset = HCI_EVENT_PREAMBLE_SIZE + 1; // Skip num packets. | |
84 | + | |
85 | + uint16_t opcode = packet[opcode_offset] | (packet[opcode_offset + 1] << 8); | |
86 | + | |
87 | + ALOGV("%s internal_command.opcode = %04X opcode = %04x", __func__, | |
88 | + internal_command.opcode, opcode); | |
89 | + return opcode == internal_command.opcode; | |
90 | +} | |
91 | + | |
92 | +uint8_t transmit_cb(uint16_t opcode, void* buffer, tINT_CMD_CBACK callback) { | |
93 | + ALOGV("%s opcode: 0x%04x, ptr: %p, cb: %p", __func__, opcode, buffer, | |
94 | + callback); | |
95 | + internal_command.cb = callback; | |
96 | + internal_command.opcode = opcode; | |
97 | + uint8_t type = HCI_PACKET_TYPE_COMMAND; | |
98 | + HC_BT_HDR* bt_hdr = reinterpret_cast<HC_BT_HDR*>(buffer); | |
99 | + VendorInterface::get()->Send(type, bt_hdr->data, bt_hdr->len); | |
100 | + delete[] reinterpret_cast<uint8_t*>(buffer); | |
101 | + return true; | |
102 | +} | |
103 | + | |
104 | +void firmware_config_cb(bt_vendor_op_result_t result) { | |
105 | + ALOGV("%s result: %d", __func__, result); | |
106 | + VendorInterface::get()->OnFirmwareConfigured(result); | |
107 | +} | |
108 | + | |
109 | +void sco_config_cb(bt_vendor_op_result_t result) { | |
110 | + ALOGD("%s result: %d", __func__, result); | |
111 | +} | |
112 | + | |
113 | +void low_power_mode_cb(bt_vendor_op_result_t result) { | |
114 | + ALOGD("%s result: %d", __func__, result); | |
115 | +} | |
116 | + | |
117 | +void sco_audiostate_cb(bt_vendor_op_result_t result) { | |
118 | + ALOGD("%s result: %d", __func__, result); | |
119 | +} | |
120 | + | |
121 | +void* buffer_alloc_cb(int size) { | |
122 | + void* p = new uint8_t[size]; | |
123 | + ALOGV("%s pts: %p, size: %d", __func__, p, size); | |
124 | + return p; | |
125 | +} | |
126 | + | |
127 | +void buffer_free_cb(void* buffer) { | |
128 | + ALOGV("%s ptr: %p", __func__, buffer); | |
129 | + delete[] reinterpret_cast<uint8_t*>(buffer); | |
130 | +} | |
131 | + | |
132 | +void epilog_cb(bt_vendor_op_result_t result) { | |
133 | + ALOGD("%s result: %d", __func__, result); | |
134 | +} | |
135 | + | |
136 | +void a2dp_offload_cb(bt_vendor_op_result_t result, bt_vendor_opcode_t op, | |
137 | + uint8_t av_handle) { | |
138 | + ALOGD("%s result: %d, op: %d, handle: %d", __func__, result, op, av_handle); | |
139 | +} | |
140 | + | |
141 | +const bt_vendor_callbacks_t lib_callbacks = { | |
142 | + sizeof(lib_callbacks), firmware_config_cb, sco_config_cb, | |
143 | + low_power_mode_cb, sco_audiostate_cb, buffer_alloc_cb, | |
144 | + buffer_free_cb, transmit_cb, epilog_cb, | |
145 | + a2dp_offload_cb}; | |
146 | + | |
147 | +} // namespace | |
148 | + | |
149 | +namespace android { | |
150 | +namespace hardware { | |
151 | +namespace bluetooth { | |
152 | +namespace V1_0 { | |
153 | +namespace implementation { | |
154 | + | |
155 | +class FirmwareStartupTimer { | |
156 | + public: | |
157 | + FirmwareStartupTimer() : start_time_(std::chrono::steady_clock::now()) {} | |
158 | + | |
159 | + ~FirmwareStartupTimer() { | |
160 | + std::chrono::duration<double> duration = | |
161 | + std::chrono::steady_clock::now() - start_time_; | |
162 | + double s = duration.count(); | |
163 | + if (s == 0) return; | |
164 | + ALOGI("Firmware configured in %.3fs", s); | |
165 | + } | |
166 | + | |
167 | + private: | |
168 | + std::chrono::steady_clock::time_point start_time_; | |
169 | +}; | |
170 | + | |
171 | +bool VendorInterface::Initialize( | |
172 | + InitializeCompleteCallback initialize_complete_cb, | |
173 | + PacketReadCallback event_cb, PacketReadCallback acl_cb, | |
174 | + PacketReadCallback sco_cb) { | |
175 | + if (g_vendor_interface) { | |
176 | + ALOGE("%s: No previous Shutdown()?", __func__); | |
177 | + return false; | |
178 | + } | |
179 | + g_vendor_interface = new VendorInterface(); | |
180 | + return g_vendor_interface->Open(initialize_complete_cb, event_cb, acl_cb, | |
181 | + sco_cb); | |
182 | +} | |
183 | + | |
184 | +void VendorInterface::Shutdown() { | |
185 | + LOG_ALWAYS_FATAL_IF(!g_vendor_interface, "%s: No Vendor interface!", | |
186 | + __func__); | |
187 | + g_vendor_interface->Close(); | |
188 | + delete g_vendor_interface; | |
189 | + g_vendor_interface = nullptr; | |
190 | +} | |
191 | + | |
192 | +VendorInterface* VendorInterface::get() { return g_vendor_interface; } | |
193 | + | |
194 | +bool VendorInterface::Open(InitializeCompleteCallback initialize_complete_cb, | |
195 | + PacketReadCallback event_cb, | |
196 | + PacketReadCallback acl_cb, | |
197 | + PacketReadCallback sco_cb) { | |
198 | + initialize_complete_cb_ = initialize_complete_cb; | |
199 | + | |
200 | + // Initialize vendor interface | |
201 | + | |
202 | + lib_handle_ = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW); | |
203 | + if (!lib_handle_) { | |
204 | + ALOGE("%s unable to open %s (%s)", __func__, VENDOR_LIBRARY_NAME, | |
205 | + dlerror()); | |
206 | + return false; | |
207 | + } | |
208 | + | |
209 | + lib_interface_ = reinterpret_cast<bt_vendor_interface_t*>( | |
210 | + dlsym(lib_handle_, VENDOR_LIBRARY_SYMBOL_NAME)); | |
211 | + if (!lib_interface_) { | |
212 | + ALOGE("%s unable to find symbol %s in %s (%s)", __func__, | |
213 | + VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror()); | |
214 | + return false; | |
215 | + } | |
216 | + | |
217 | + old_coding_format = ESCO_CODING_FORMAT_MSBC; | |
218 | + | |
219 | + // Get the local BD address | |
220 | + | |
221 | + uint8_t local_bda[BluetoothAddress::kBytes]; | |
222 | + if (!BluetoothAddress::get_local_address(local_bda)) { | |
223 | + LOG_ALWAYS_FATAL("%s: No Bluetooth Address!", __func__); | |
224 | + } | |
225 | + int status = lib_interface_->init(&lib_callbacks, (unsigned char*)local_bda); | |
226 | + if (status) { | |
227 | + ALOGE("%s unable to initialize vendor library: %d", __func__, status); | |
228 | + return false; | |
229 | + } | |
230 | + | |
231 | + ALOGD("%s vendor library loaded", __func__); | |
232 | + | |
233 | + // Power on the controller | |
234 | + | |
235 | + int power_state = BT_VND_PWR_ON; | |
236 | + lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state); | |
237 | + | |
238 | + // Get the UART socket(s) | |
239 | + | |
240 | + int fd_list[CH_MAX] = {0}; | |
241 | + int fd_count = lib_interface_->op(BT_VND_OP_USERIAL_OPEN, &fd_list); | |
242 | + | |
243 | + if (fd_count < 1 || fd_count > CH_MAX - 1) { | |
244 | + ALOGE("%s: fd_count %d is invalid!", __func__, fd_count); | |
245 | + return false; | |
246 | + } | |
247 | + | |
248 | + for (int i = 0; i < fd_count; i++) { | |
249 | + if (fd_list[i] == INVALID_FD) { | |
250 | + ALOGE("%s: fd %d is invalid!", __func__, fd_list[i]); | |
251 | + return false; | |
252 | + } | |
253 | + } | |
254 | + | |
255 | + event_cb_ = event_cb; | |
256 | + PacketReadCallback intercept_events = [this](const hidl_vec<uint8_t>& event) { | |
257 | + HandleIncomingEvent(event); | |
258 | + }; | |
259 | + | |
260 | + if (fd_count == 1) { | |
261 | + hci::H4Protocol* h4_hci = | |
262 | + new hci::H4Protocol(fd_list[0], intercept_events, acl_cb, sco_cb); | |
263 | + fd_watcher_.WatchFdForNonBlockingReads( | |
264 | + fd_list[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); }); | |
265 | + hci_ = h4_hci; | |
266 | + } else { | |
267 | + hci::MctProtocol* mct_hci = | |
268 | + new hci::MctProtocol(fd_list, intercept_events, acl_cb); | |
269 | + fd_watcher_.WatchFdForNonBlockingReads( | |
270 | + fd_list[CH_EVT], [mct_hci](int fd) { mct_hci->OnEventDataReady(fd); }); | |
271 | + fd_watcher_.WatchFdForNonBlockingReads( | |
272 | + fd_list[CH_ACL_IN], | |
273 | + [mct_hci](int fd) { mct_hci->OnAclDataReady(fd); }); | |
274 | + hci_ = mct_hci; | |
275 | + } | |
276 | + | |
277 | + // Initially, the power management is off. | |
278 | + lpm_wake_deasserted = true; | |
279 | + | |
280 | + // Start configuring the firmware | |
281 | + firmware_startup_timer_ = new FirmwareStartupTimer(); | |
282 | + lib_interface_->op(BT_VND_OP_FW_CFG, nullptr); | |
283 | + | |
284 | + return true; | |
285 | +} | |
286 | + | |
287 | +void VendorInterface::Close() { | |
288 | + // These callbacks may send HCI events (vendor-dependent), so make sure to | |
289 | + // StopWatching the file descriptor after this. | |
290 | + if (lib_interface_ != nullptr) { | |
291 | + bt_vendor_lpm_mode_t mode = BT_VND_LPM_DISABLE; | |
292 | + lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode); | |
293 | + } | |
294 | + | |
295 | + fd_watcher_.StopWatchingFileDescriptors(); | |
296 | + | |
297 | + if (hci_ != nullptr) { | |
298 | + delete hci_; | |
299 | + hci_ = nullptr; | |
300 | + } | |
301 | + | |
302 | + if (lib_interface_ != nullptr) { | |
303 | + lib_interface_->op(BT_VND_OP_USERIAL_CLOSE, nullptr); | |
304 | + | |
305 | + int power_state = BT_VND_PWR_OFF; | |
306 | + lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state); | |
307 | + | |
308 | + lib_interface_->cleanup(); | |
309 | + } | |
310 | + | |
311 | + if (lib_handle_ != nullptr) { | |
312 | + dlclose(lib_handle_); | |
313 | + lib_handle_ = nullptr; | |
314 | + } | |
315 | + | |
316 | + if (firmware_startup_timer_ != nullptr) { | |
317 | + delete firmware_startup_timer_; | |
318 | + firmware_startup_timer_ = nullptr; | |
319 | + } | |
320 | +} | |
321 | + | |
322 | +size_t VendorInterface::Send(uint8_t type, const uint8_t* data, size_t length) { | |
323 | + std::unique_lock<std::mutex> lock(wakeup_mutex_); | |
324 | + recent_activity_flag = true; | |
325 | + | |
326 | + if (lpm_wake_deasserted == true) { | |
327 | + // Restart the timer. | |
328 | + fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms), | |
329 | + [this]() { OnTimeout(); }); | |
330 | + // Assert wake. | |
331 | + lpm_wake_deasserted = false; | |
332 | + bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_ASSERT; | |
333 | + lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState); | |
334 | + ALOGV("%s: Sent wake before (%02x)", __func__, data[0] | (data[1] << 8)); | |
335 | + } | |
336 | + if (type == HCI_PACKET_TYPE_COMMAND) { | |
337 | + uint8_t* p; | |
338 | + uint16_t command; | |
339 | + uint8_t coding_format = 0; | |
340 | + int codec = 0x02; | |
341 | + p = (uint8_t*)data; | |
342 | + STREAM_TO_UINT16(command, p); | |
343 | + | |
344 | + if (command == HCI_ENH_ACCEPT_ESCO_CONNECTION) { | |
345 | + p += 15; // Increment stream pointer to point to the coding format byte | |
346 | + STREAM_TO_UINT8(coding_format, p); | |
347 | + } else if (command == HCI_ENH_SETUP_ESCO_CONNECTION) { | |
348 | + p += 11; // Increment stream pointer to point to the coding format byte | |
349 | + STREAM_TO_UINT8(coding_format, p); | |
350 | + } | |
351 | + if (coding_format != 0 && coding_format != old_coding_format) { | |
352 | + if (coding_format == ESCO_CODING_FORMAT_MSBC) { | |
353 | + codec = 0x02; | |
354 | + } else if (coding_format == ESCO_CODING_FORMAT_CVSD) { | |
355 | + codec = 0x01; | |
356 | + } | |
357 | + | |
358 | + old_coding_format = coding_format; | |
359 | + lib_interface_->op(BT_VND_OP_SET_AUDIO_STATE, (int*)&codec); | |
360 | + } | |
361 | + } | |
362 | + | |
363 | + return hci_->Send(type, data, length); | |
364 | +} | |
365 | + | |
366 | +void VendorInterface::OnFirmwareConfigured(uint8_t result) { | |
367 | + ALOGD("%s result: %d", __func__, result); | |
368 | + | |
369 | + if (firmware_startup_timer_ != nullptr) { | |
370 | + delete firmware_startup_timer_; | |
371 | + firmware_startup_timer_ = nullptr; | |
372 | + } | |
373 | + | |
374 | + if (initialize_complete_cb_ != nullptr) { | |
375 | + initialize_complete_cb_(result == 0); | |
376 | + initialize_complete_cb_ = nullptr; | |
377 | + } | |
378 | + | |
379 | + // Post load | |
380 | + lib_interface_->op(BT_VND_OP_SCO_CFG, NULL); | |
381 | + ALOGI("%s: SCO configuration initiated ", __func__); | |
382 | + | |
383 | + lib_interface_->op(BT_VND_OP_GET_LPM_IDLE_TIMEOUT, &lpm_timeout_ms); | |
384 | + ALOGI("%s: lpm_timeout_ms %d", __func__, lpm_timeout_ms); | |
385 | + | |
386 | + bt_vendor_lpm_mode_t mode = BT_VND_LPM_ENABLE; | |
387 | + lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode); | |
388 | + | |
389 | + ALOGD("%s Calling StartLowPowerWatchdog()", __func__); | |
390 | + fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms), | |
391 | + [this]() { OnTimeout(); }); | |
392 | +} | |
393 | + | |
394 | +void VendorInterface::OnTimeout() { | |
395 | + ALOGV("%s", __func__); | |
396 | + std::unique_lock<std::mutex> lock(wakeup_mutex_); | |
397 | + if (recent_activity_flag == false) { | |
398 | + lpm_wake_deasserted = true; | |
399 | + bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_DEASSERT; | |
400 | + lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState); | |
401 | + fd_watcher_.ConfigureTimeout(std::chrono::seconds(0), []() { | |
402 | + ALOGE("Zero timeout! Should never happen."); | |
403 | + }); | |
404 | + } | |
405 | + recent_activity_flag = false; | |
406 | +} | |
407 | + | |
408 | +void VendorInterface::HandleIncomingEvent(const hidl_vec<uint8_t>& hci_packet) { | |
409 | + if (internal_command.cb != nullptr && | |
410 | + internal_command_event_match(hci_packet)) { | |
411 | + HC_BT_HDR* bt_hdr = WrapPacketAndCopy(HCI_PACKET_TYPE_EVENT, hci_packet); | |
412 | + | |
413 | + // The callbacks can send new commands, so don't zero after calling. | |
414 | + tINT_CMD_CBACK saved_cb = internal_command.cb; | |
415 | + internal_command.cb = nullptr; | |
416 | + saved_cb(bt_hdr); | |
417 | + } else { | |
418 | + event_cb_(hci_packet); | |
419 | + } | |
420 | +} | |
421 | + | |
422 | +} // namespace implementation | |
423 | +} // namespace V1_0 | |
424 | +} // namespace bluetooth | |
425 | +} // namespace hardware | |
426 | +} // namespace android |
@@ -0,0 +1,77 @@ | ||
1 | +// | |
2 | +// Copyright 2016 The Android Open Source Project | |
3 | +// | |
4 | +// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +// you may not use this file except in compliance with the License. | |
6 | +// You may obtain a copy of the License at | |
7 | +// | |
8 | +// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +// | |
10 | +// Unless required by applicable law or agreed to in writing, software | |
11 | +// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +// See the License for the specific language governing permissions and | |
14 | +// limitations under the License. | |
15 | +// | |
16 | + | |
17 | +#pragma once | |
18 | + | |
19 | +#include <hidl/HidlSupport.h> | |
20 | + | |
21 | +#include "async_fd_watcher.h" | |
22 | +#include "bt_vendor_lib.h" | |
23 | +#include "hci_protocol.h" | |
24 | + | |
25 | +namespace android { | |
26 | +namespace hardware { | |
27 | +namespace bluetooth { | |
28 | +namespace V1_0 { | |
29 | +namespace implementation { | |
30 | + | |
31 | +using ::android::hardware::hidl_vec; | |
32 | +using InitializeCompleteCallback = std::function<void(bool success)>; | |
33 | +using PacketReadCallback = std::function<void(const hidl_vec<uint8_t>&)>; | |
34 | + | |
35 | +class FirmwareStartupTimer; | |
36 | + | |
37 | +class VendorInterface { | |
38 | + public: | |
39 | + static bool Initialize(InitializeCompleteCallback initialize_complete_cb, | |
40 | + PacketReadCallback event_cb, PacketReadCallback acl_cb, | |
41 | + PacketReadCallback sco_cb); | |
42 | + static void Shutdown(); | |
43 | + static VendorInterface *get(); | |
44 | + | |
45 | + size_t Send(uint8_t type, const uint8_t *data, size_t length); | |
46 | + | |
47 | + void OnFirmwareConfigured(uint8_t result); | |
48 | + | |
49 | + private: | |
50 | + virtual ~VendorInterface() = default; | |
51 | + | |
52 | + bool Open(InitializeCompleteCallback initialize_complete_cb, | |
53 | + PacketReadCallback event_cb, PacketReadCallback acl_cb, | |
54 | + PacketReadCallback sco_cb); | |
55 | + void Close(); | |
56 | + | |
57 | + void OnTimeout(); | |
58 | + | |
59 | + void HandleIncomingEvent(const hidl_vec<uint8_t>& hci_packet); | |
60 | + | |
61 | + void *lib_handle_; | |
62 | + bt_vendor_interface_t *lib_interface_; | |
63 | + async::AsyncFdWatcher fd_watcher_; | |
64 | + InitializeCompleteCallback initialize_complete_cb_; | |
65 | + hci::HciProtocol* hci_; | |
66 | + | |
67 | + PacketReadCallback event_cb_; | |
68 | + | |
69 | + FirmwareStartupTimer *firmware_startup_timer_; | |
70 | + uint8_t old_coding_format; | |
71 | +}; | |
72 | + | |
73 | +} // namespace implementation | |
74 | +} // namespace V1_0 | |
75 | +} // namespace bluetooth | |
76 | +} // namespace hardware | |
77 | +} // namespace android |