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 "h4_protocol.h"
18
19 #define LOG_TAG "android.hardware.bluetooth-hci-h4"
20 #include <android-base/logging.h>
21 #include <assert.h>
22 #include <fcntl.h>
23 #include <sys/uio.h>
24 #include <utils/Log.h>
25
26 namespace android {
27 namespace hardware {
28 namespace bluetooth {
29 namespace hci {
30
H4Protocol(int fd,PacketReadCallback event_cb,PacketReadCallback acl_cb,PacketReadCallback sco_cb,PacketReadCallback iso_cb,OnDisconnectCallback disconnect_cb)31 H4Protocol::H4Protocol(int fd, PacketReadCallback event_cb,
32 PacketReadCallback acl_cb, PacketReadCallback sco_cb,
33 PacketReadCallback iso_cb,
34 OnDisconnectCallback disconnect_cb)
35 : uart_fd_(fd),
36 event_cb_(std::move(event_cb)),
37 acl_cb_(std::move(acl_cb)),
38 sco_cb_(std::move(sco_cb)),
39 iso_cb_(std::move(iso_cb)),
40 disconnect_cb_(std::move(disconnect_cb)) {}
41
Send(uint8_t type,const uint8_t * data,size_t length)42 size_t H4Protocol::Send(uint8_t type, const uint8_t* data, size_t length) {
43 /* For HCI communication over USB dongle, multiple write results in
44 * response timeout as driver expect type + data at once to process
45 * the command, so using "writev"(for atomicity) here.
46 */
47 struct iovec iov[2];
48 ssize_t ret = 0;
49 iov[0].iov_base = &type;
50 iov[0].iov_len = sizeof(type);
51 iov[1].iov_base = (void *)data;
52 iov[1].iov_len = length;
53 while (1) {
54 ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, 2));
55 if (ret == -1) {
56 if (errno == EAGAIN) {
57 ALOGE("%s error writing to UART (%s)", __func__, strerror(errno));
58 continue;
59 }
60 } else if (ret == 0) {
61 // Nothing written :(
62 ALOGE("%s zero bytes written - something went wrong...", __func__);
63 break;
64 }
65 break;
66 }
67 return ret;
68 }
69
on_packet_ready(const hidl_vec<uint8_t> & packet)70 size_t H4Protocol::on_packet_ready(const hidl_vec<uint8_t>& packet) {
71 switch (hci_packet_type_) {
72 case HCI_PACKET_TYPE_EVENT:
73 event_cb_(packet);
74 break;
75 case HCI_PACKET_TYPE_ACL_DATA:
76 acl_cb_(packet);
77 break;
78 case HCI_PACKET_TYPE_SCO_DATA:
79 sco_cb_(packet);
80 break;
81 case HCI_PACKET_TYPE_ISO_DATA:
82 iso_cb_(packet);
83 break;
84 default: {
85 LOG_ALWAYS_FATAL("Unhandled packet of type 0x%x", hci_packet_type_);
86 }
87 }
88 return packet.size();
89 }
90
send_data_to_packetizer(uint8_t * buffer,size_t length)91 void H4Protocol::send_data_to_packetizer(uint8_t* buffer, size_t length) {
92 std::vector<uint8_t> input_buffer{buffer, buffer + length};
93 size_t buffer_offset = 0;
94 while (buffer_offset < input_buffer.size()) {
95 if (hci_packet_type_ == HCI_PACKET_TYPE_UNKNOWN) {
96 hci_packet_type_ =
97 static_cast<HciPacketType>(input_buffer.data()[buffer_offset]);
98 buffer_offset += 1;
99 } else {
100 bool packet_ready = hci_packetizer_.OnDataReady(
101 hci_packet_type_, input_buffer, buffer_offset);
102 if (packet_ready) {
103 // Call packet callback and move offset.
104 buffer_offset += on_packet_ready(hci_packetizer_.GetPacket());
105 // Get ready for the next type byte.
106 hci_packet_type_ = HCI_PACKET_TYPE_UNKNOWN;
107 } else {
108 // The data was consumed, but there wasn't a packet.
109 buffer_offset = input_buffer.size();
110 }
111 }
112 }
113 }
114
OnDataReady(int fd)115 void H4Protocol::OnDataReady(int fd) {
116 if (disconnected_) {
117 return;
118 }
119 uint8_t buffer[kMaxPacketLength];
120 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, kMaxPacketLength));
121 if (bytes_read == 0) {
122 ALOGI("No bytes read, calling the disconnect callback");
123 disconnected_ = true;
124 disconnect_cb_();
125 return;
126 }
127 if (bytes_read < 0) {
128 ALOGW("error reading from UART (%s)", strerror(errno));
129 return;
130 }
131 send_data_to_packetizer(buffer, bytes_read);
132 }
133
134 } // namespace hci
135 } // namespace bluetooth
136 } // namespace hardware
137 } // namespace android
138