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