1 /******************************************************************************
2 *
3 * Copyright (C) 2014 Google, Inc.
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 #define LOG_TAG "bt_hci_h4"
20
21 #include <assert.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include "hci_hal.h"
27 #include "osi/include/eager_reader.h"
28 #include "osi/include/log.h"
29 #include "osi/include/osi.h"
30 #include "osi/include/reactor.h"
31 #include "osi/include/thread.h"
32 #include "vendor.h"
33
34 #define HCI_HAL_SERIAL_BUFFER_SIZE 1026
35 #define HCI_BLE_EVENT 0x3e
36
37 // Increased HCI thread priority to keep up with the audio sub-system
38 // when streaming time sensitive data (A2DP).
39 #define HCI_THREAD_PRIORITY -19
40
41 // Our interface and modules we import
42 static const hci_hal_t interface;
43 static const hci_hal_callbacks_t *callbacks;
44 static const vendor_t *vendor;
45
46 static thread_t *thread; // Not owned by us
47
48 static int uart_fd;
49 static eager_reader_t *uart_stream;
50 static serial_data_type_t current_data_type;
51 static bool stream_has_interpretation;
52 static bool stream_corruption_detected;
53 static uint8_t stream_corruption_bytes_to_ignore;
54
55 static void event_uart_has_bytes(eager_reader_t *reader, void *context);
56
57 // Interface functions
58
hal_init(const hci_hal_callbacks_t * upper_callbacks,thread_t * upper_thread)59 static bool hal_init(const hci_hal_callbacks_t *upper_callbacks, thread_t *upper_thread) {
60 assert(upper_callbacks != NULL);
61 assert(upper_thread != NULL);
62
63 callbacks = upper_callbacks;
64 thread = upper_thread;
65 return true;
66 }
67
hal_open()68 static bool hal_open() {
69 LOG_INFO(LOG_TAG, "%s", __func__);
70 // TODO(zachoverflow): close if already open / or don't reopen (maybe at the hci layer level)
71
72 int fd_array[CH_MAX];
73 int number_of_ports = vendor->send_command(VENDOR_OPEN_USERIAL, &fd_array);
74
75 if (number_of_ports != 1) {
76 LOG_ERROR(LOG_TAG, "%s opened the wrong number of ports: got %d, expected 1.", __func__, number_of_ports);
77 goto error;
78 }
79
80 uart_fd = fd_array[0];
81 if (uart_fd == INVALID_FD) {
82 LOG_ERROR(LOG_TAG, "%s unable to open the uart serial port.", __func__);
83 goto error;
84 }
85
86 uart_stream = eager_reader_new(uart_fd, &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_single_channel");
87 if (!uart_stream) {
88 LOG_ERROR(LOG_TAG, "%s unable to create eager reader for the uart serial port.", __func__);
89 goto error;
90 }
91
92 stream_has_interpretation = false;
93 stream_corruption_detected = false;
94 stream_corruption_bytes_to_ignore = 0;
95 eager_reader_register(uart_stream, thread_get_reactor(thread), event_uart_has_bytes, NULL);
96
97 // Raise thread priorities to keep up with audio
98 thread_set_priority(thread, HCI_THREAD_PRIORITY);
99 thread_set_priority(eager_reader_get_read_thread(uart_stream), HCI_THREAD_PRIORITY);
100
101 return true;
102
103 error:
104 interface.close();
105 return false;
106 }
107
hal_close()108 static void hal_close() {
109 LOG_INFO(LOG_TAG, "%s", __func__);
110
111 eager_reader_free(uart_stream);
112 vendor->send_command(VENDOR_CLOSE_USERIAL, NULL);
113 uart_fd = INVALID_FD;
114 }
115
read_data(serial_data_type_t type,uint8_t * buffer,size_t max_size)116 static size_t read_data(serial_data_type_t type, uint8_t *buffer, size_t max_size) {
117 if (type < DATA_TYPE_ACL || type > DATA_TYPE_EVENT) {
118 LOG_ERROR(LOG_TAG, "%s invalid data type: %d", __func__, type);
119 return 0;
120 } else if (!stream_has_interpretation) {
121 LOG_ERROR(LOG_TAG, "%s with no valid stream intepretation.", __func__);
122 return 0;
123 } else if (current_data_type != type) {
124 LOG_ERROR(LOG_TAG, "%s with different type than existing interpretation.", __func__);
125 return 0;
126 }
127
128 return eager_reader_read(uart_stream, buffer, max_size);
129 }
130
packet_finished(serial_data_type_t type)131 static void packet_finished(serial_data_type_t type) {
132 if (!stream_has_interpretation)
133 LOG_ERROR(LOG_TAG, "%s with no existing stream interpretation.", __func__);
134 else if (current_data_type != type)
135 LOG_ERROR(LOG_TAG, "%s with different type than existing interpretation.", __func__);
136
137 stream_has_interpretation = false;
138 }
139
transmit_data(serial_data_type_t type,uint8_t * data,uint16_t length)140 static uint16_t transmit_data(serial_data_type_t type, uint8_t *data, uint16_t length) {
141 assert(data != NULL);
142 assert(length > 0);
143
144 if (type < DATA_TYPE_COMMAND || type > DATA_TYPE_SCO) {
145 LOG_ERROR(LOG_TAG, "%s invalid data type: %d", __func__, type);
146 return 0;
147 }
148
149 // Write the signal byte right before the data
150 --data;
151 uint8_t previous_byte = *data;
152 *(data) = type;
153 ++length;
154
155 uint16_t transmitted_length = 0;
156 while (length > 0) {
157 ssize_t ret;
158 OSI_NO_INTR(ret = write(uart_fd, data + transmitted_length, length));
159 switch (ret) {
160 case -1:
161 LOG_ERROR(LOG_TAG, "In %s, error writing to the uart serial port: %s", __func__, strerror(errno));
162 goto done;
163 case 0:
164 // If we wrote nothing, don't loop more because we
165 // can't go to infinity or beyond
166 goto done;
167 default:
168 transmitted_length += ret;
169 length -= ret;
170 break;
171 }
172 }
173
174 done:;
175 // Be nice and restore the old value of that byte
176 *(data) = previous_byte;
177
178 // Remove the signal byte from our transmitted length, if it was actually written
179 if (transmitted_length > 0)
180 --transmitted_length;
181
182 return transmitted_length;
183 }
184
185 // Internal functions
186
187 // WORKAROUND:
188 // As exhibited by b/23934838, during result-heavy LE scans, the UART byte
189 // stream can get corrupted, leading to assertions caused by mis-interpreting
190 // the bytes following the corruption.
191 // This workaround looks for tell-tale signs of a BLE event and attempts to
192 // skip the correct amount of bytes in the stream to re-synchronize onto
193 // a packet boundary.
194 // Function returns true if |byte_read| has been processed by the workaround.
stream_corrupted_during_le_scan_workaround(const uint8_t byte_read)195 static bool stream_corrupted_during_le_scan_workaround(const uint8_t byte_read)
196 {
197 if (!stream_corruption_detected && byte_read == HCI_BLE_EVENT) {
198 LOG_ERROR(LOG_TAG, "%s HCI stream corrupted (message type 0x3E)!", __func__);
199 stream_corruption_detected = true;
200 return true;
201 }
202
203 if (stream_corruption_detected) {
204 if (stream_corruption_bytes_to_ignore == 0) {
205 stream_corruption_bytes_to_ignore = byte_read;
206 LOG_ERROR(LOG_TAG, "%s About to skip %d bytes...", __func__, stream_corruption_bytes_to_ignore);
207 } else {
208 --stream_corruption_bytes_to_ignore;
209 }
210
211 if (stream_corruption_bytes_to_ignore == 0) {
212 LOG_ERROR(LOG_TAG, "%s Back to our regularly scheduled program...", __func__);
213 stream_corruption_detected = false;
214 }
215 return true;
216 }
217
218 return false;
219 }
220
221 // See what data is waiting, and notify the upper layer
event_uart_has_bytes(eager_reader_t * reader,UNUSED_ATTR void * context)222 static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *context) {
223 if (stream_has_interpretation) {
224 callbacks->data_ready(current_data_type);
225 } else {
226 uint8_t type_byte;
227 if (eager_reader_read(reader, &type_byte, 1) == 0) {
228 LOG_ERROR(LOG_TAG, "%s could not read HCI message type", __func__);
229 return;
230 }
231
232 if (stream_corrupted_during_le_scan_workaround(type_byte))
233 return;
234
235 if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) {
236 LOG_ERROR(LOG_TAG, "%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__, type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT);
237 return;
238 }
239
240 stream_has_interpretation = true;
241 current_data_type = type_byte;
242 }
243 }
244
245 static const hci_hal_t interface = {
246 hal_init,
247
248 hal_open,
249 hal_close,
250
251 read_data,
252 packet_finished,
253 transmit_data,
254 };
255
hci_hal_h4_get_interface()256 const hci_hal_t *hci_hal_h4_get_interface() {
257 vendor = vendor_get_interface();
258 return &interface;
259 }
260
hci_hal_h4_get_test_interface(vendor_t * vendor_interface)261 const hci_hal_t *hci_hal_h4_get_test_interface(vendor_t *vendor_interface) {
262 vendor = vendor_interface;
263 return &interface;
264 }
265