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