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_mct"
20
21#include <assert.h>
22#include <errno.h>
23#include <string.h>
24
25#include "bt_vendor_lib.h"
26#include "osi/include/eager_reader.h"
27#include "hci_hal.h"
28#include "osi/include/osi.h"
29#include "osi/include/log.h"
30#include "osi/include/reactor.h"
31#include "vendor.h"
32
33#define HCI_HAL_SERIAL_BUFFER_SIZE 1026
34
35// Our interface and modules we import
36static const hci_hal_t interface;
37static const hci_hal_callbacks_t *callbacks;
38static const vendor_t *vendor;
39
40static thread_t *thread; // Not owned by us
41
42static int uart_fds[CH_MAX];
43static eager_reader_t *event_stream;
44static eager_reader_t *acl_stream;
45
46static uint16_t transmit_data_on(int fd, uint8_t *data, uint16_t length);
47static void event_event_stream_has_bytes(eager_reader_t *reader, void *context);
48static void event_acl_stream_has_bytes(eager_reader_t *reader, void *context);
49
50// Interface functions
51
52static bool hal_init(const hci_hal_callbacks_t *upper_callbacks, thread_t *upper_thread) {
53  assert(upper_callbacks != NULL);
54  assert(upper_thread != NULL);
55
56  callbacks = upper_callbacks;
57  thread = upper_thread;
58  return true;
59}
60
61static bool hal_open() {
62  LOG_INFO("%s", __func__);
63  // TODO(zachoverflow): close if already open / or don't reopen (maybe at the hci layer level)
64
65  int number_of_ports = vendor->send_command(VENDOR_OPEN_USERIAL, &uart_fds);
66
67  if (number_of_ports != 2 && number_of_ports != 4) {
68    LOG_ERROR("%s opened the wrong number of ports: got %d, expected 2 or 4.", __func__, number_of_ports);
69    goto error;
70  }
71
72  LOG_INFO("%s got uart fds: CMD=%d, EVT=%d, ACL_OUT=%d, ACL_IN=%d",
73      __func__, uart_fds[CH_CMD], uart_fds[CH_EVT], uart_fds[CH_ACL_OUT], uart_fds[CH_ACL_IN]);
74
75  if (uart_fds[CH_CMD] == INVALID_FD) {
76    LOG_ERROR("%s unable to open the command uart serial port.", __func__);
77    goto error;
78  }
79
80  if (uart_fds[CH_EVT] == INVALID_FD) {
81    LOG_ERROR("%s unable to open the event uart serial port.", __func__);
82    goto error;
83  }
84
85  if (uart_fds[CH_ACL_OUT] == INVALID_FD) {
86    LOG_ERROR("%s unable to open the acl-out uart serial port.", __func__);
87    goto error;
88  }
89
90  if (uart_fds[CH_ACL_IN] == INVALID_FD) {
91    LOG_ERROR("%s unable to open the acl-in uart serial port.", __func__);
92    goto error;
93  }
94
95  event_stream = eager_reader_new(uart_fds[CH_EVT], &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_mct");
96  if (!event_stream) {
97    LOG_ERROR("%s unable to create eager reader for the event uart serial port.", __func__);
98    goto error;
99  }
100
101  acl_stream = eager_reader_new(uart_fds[CH_ACL_IN], &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_mct");
102  if (!event_stream) {
103    LOG_ERROR("%s unable to create eager reader for the acl-in uart serial port.", __func__);
104    goto error;
105  }
106
107  eager_reader_register(event_stream, thread_get_reactor(thread), event_event_stream_has_bytes, NULL);
108  eager_reader_register(acl_stream, thread_get_reactor(thread), event_acl_stream_has_bytes, NULL);
109
110  return true;
111
112error:;
113  interface.close();
114  return false;
115}
116
117static void hal_close() {
118  LOG_INFO("%s", __func__);
119
120  eager_reader_free(event_stream);
121  eager_reader_free(acl_stream);
122  vendor->send_command(VENDOR_CLOSE_USERIAL, NULL);
123
124  for (int i = 0; i < CH_MAX; i++)
125    uart_fds[i] = INVALID_FD;
126}
127
128static size_t read_data(serial_data_type_t type, uint8_t *buffer, size_t max_size, bool block) {
129  if (type == DATA_TYPE_ACL) {
130    return eager_reader_read(acl_stream, buffer, max_size, block);
131  } else if (type == DATA_TYPE_EVENT) {
132    return eager_reader_read(event_stream, buffer, max_size, block);
133  }
134
135  LOG_ERROR("%s invalid data type: %d", __func__, type);
136  return 0;
137}
138
139static void packet_finished(UNUSED_ATTR serial_data_type_t type) {
140  // not needed by this protocol
141}
142
143static uint16_t transmit_data(serial_data_type_t type, uint8_t *data, uint16_t length) {
144  if (type == DATA_TYPE_ACL) {
145    return transmit_data_on(uart_fds[CH_ACL_OUT], data, length);
146  } else if (type == DATA_TYPE_COMMAND) {
147    return transmit_data_on(uart_fds[CH_CMD], data, length);
148  }
149
150  LOG_ERROR("%s invalid data type: %d", __func__, type);
151  return 0;
152}
153
154// Internal functions
155
156static uint16_t transmit_data_on(int fd, uint8_t *data, uint16_t length) {
157  assert(data != NULL);
158  assert(length > 0);
159
160  uint16_t transmitted_length = 0;
161  while (length > 0) {
162    ssize_t ret = write(fd, data + transmitted_length, length);
163    switch (ret) {
164      case -1:
165        LOG_ERROR("In %s, error writing to the serial port with fd %d: %s", __func__, fd, strerror(errno));
166        return transmitted_length;
167      case 0:
168        // If we wrote nothing, don't loop more because we
169        // can't go to infinity or beyond
170        return transmitted_length;
171      default:
172        transmitted_length += ret;
173        length -= ret;
174        break;
175    }
176  }
177
178  return transmitted_length;
179}
180
181static void event_event_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
182  callbacks->data_ready(DATA_TYPE_EVENT);
183}
184
185static void event_acl_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
186  // No real concept of incoming SCO typed data, just ACL
187  callbacks->data_ready(DATA_TYPE_ACL);
188}
189
190static const hci_hal_t interface = {
191  hal_init,
192
193  hal_open,
194  hal_close,
195
196  read_data,
197  packet_finished,
198  transmit_data,
199};
200
201const hci_hal_t *hci_hal_mct_get_interface() {
202  vendor = vendor_get_interface();
203  return &interface;
204}
205
206const hci_hal_t *hci_hal_mct_get_test_interface(vendor_t *vendor_interface) {
207  vendor = vendor_interface;
208  return &interface;
209}
210