• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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