1 //
2 // Copyright 20 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 "model/devices/h4_parser.h" // for H4Parser, PacketType, H4Pars...
18
19 #include <stddef.h> // for size_t
20 #include <cstdint> // for uint8_t, int32_t
21 #include <functional> // for function
22 #include <utility> // for move
23 #include <vector> // for vector
24
25 #include "model/devices/hci_protocol.h" // for PacketReadCallback
26 #include "os/log.h" // for LOG_ALWAYS_FATAL, LOG_INFO
27
28 namespace test_vendor_lib {
29
Reset()30 void H4Parser::Reset() {
31 state_ = HCI_TYPE;
32 packet_.clear();
33 bytes_wanted_ = 0;
34 packet_type_ = 0;
35 }
36
HciGetPacketLengthForType(PacketType type,const uint8_t * preamble) const37 size_t H4Parser::HciGetPacketLengthForType(PacketType type,
38 const uint8_t* preamble) const {
39 static const size_t
40 packet_length_offset[static_cast<size_t>(PacketType::ISO) + 1] = {
41 0,
42 H4Parser::COMMAND_LENGTH_OFFSET,
43 H4Parser::ACL_LENGTH_OFFSET,
44 H4Parser::SCO_LENGTH_OFFSET,
45 H4Parser::EVENT_LENGTH_OFFSET,
46 H4Parser::ISO_LENGTH_OFFSET,
47 };
48
49 size_t offset = packet_length_offset[static_cast<size_t>(type)];
50 size_t size = preamble[offset];
51 if (type == PacketType::ACL) {
52 size |= ((size_t)preamble[offset + 1]) << 8u;
53 }
54 if (type == PacketType::ISO) {
55 size |= ((size_t)preamble[offset + 1] & 0x0fu) << 8u;
56 }
57 return size;
58 }
59
H4Parser(PacketReadCallback command_cb,PacketReadCallback event_cb,PacketReadCallback acl_cb,PacketReadCallback sco_cb,PacketReadCallback iso_cb)60 H4Parser::H4Parser(PacketReadCallback command_cb, PacketReadCallback event_cb,
61 PacketReadCallback acl_cb, PacketReadCallback sco_cb,
62 PacketReadCallback iso_cb)
63 : command_cb_(std::move(command_cb)),
64 event_cb_(std::move(event_cb)),
65 acl_cb_(std::move(acl_cb)),
66 sco_cb_(std::move(sco_cb)),
67 iso_cb_(std::move(iso_cb)) {}
68
OnPacketReady()69 void H4Parser::OnPacketReady() {
70 switch (hci_packet_type_) {
71 case PacketType::COMMAND:
72 command_cb_(packet_);
73 break;
74 case PacketType::ACL:
75 acl_cb_(packet_);
76 break;
77 case PacketType::SCO:
78 sco_cb_(packet_);
79 break;
80 case PacketType::EVENT:
81 event_cb_(packet_);
82 break;
83 case PacketType::ISO:
84 iso_cb_(packet_);
85 break;
86 default:
87 LOG_ALWAYS_FATAL("Unimplemented packet type %d",
88 static_cast<int>(hci_packet_type_));
89 }
90 // Get ready for the next type byte.
91 hci_packet_type_ = PacketType::UNKNOWN;
92 }
93
BytesRequested()94 size_t H4Parser::BytesRequested() {
95 switch (state_) {
96 case HCI_TYPE:
97 return 1;
98 case HCI_PREAMBLE:
99 case HCI_PAYLOAD:
100 return bytes_wanted_;
101 }
102 }
103
Consume(uint8_t * buffer,int32_t bytes_read)104 bool H4Parser::Consume(uint8_t* buffer, int32_t bytes_read) {
105 size_t bytes_to_read = BytesRequested();
106 if (bytes_read <= 0) {
107 LOG_INFO("remote disconnected, or unhandled error?");
108 return false;
109 } else if (bytes_read > BytesRequested()) {
110 LOG_ALWAYS_FATAL("More bytes read (%u) than expected (%u)!",
111 static_cast<int>(bytes_read),
112 static_cast<int>(bytes_to_read));
113 }
114
115 static const size_t preamble_size[static_cast<size_t>(PacketType::ISO) + 1] =
116 {
117 0,
118 H4Parser::COMMAND_PREAMBLE_SIZE,
119 H4Parser::ACL_PREAMBLE_SIZE,
120 H4Parser::SCO_PREAMBLE_SIZE,
121 H4Parser::EVENT_PREAMBLE_SIZE,
122 H4Parser::ISO_PREAMBLE_SIZE,
123 };
124 switch (state_) {
125 case HCI_TYPE:
126 // bytes_read >= 1
127 packet_type_ = *buffer;
128 packet_.clear();
129 break;
130 case HCI_PREAMBLE:
131 case HCI_PAYLOAD:
132 packet_.insert(packet_.end(), buffer, buffer + bytes_read);
133 bytes_wanted_ -= bytes_read;
134 break;
135 }
136
137 switch (state_) {
138 case HCI_TYPE:
139 hci_packet_type_ = static_cast<PacketType>(packet_type_);
140 if (hci_packet_type_ != PacketType::ACL &&
141 hci_packet_type_ != PacketType::SCO &&
142 hci_packet_type_ != PacketType::COMMAND &&
143 hci_packet_type_ != PacketType::EVENT &&
144 hci_packet_type_ != PacketType::ISO) {
145 LOG_ALWAYS_FATAL("Unimplemented packet type %hhd", packet_type_);
146 }
147 state_ = HCI_PREAMBLE;
148 bytes_wanted_ = preamble_size[static_cast<size_t>(hci_packet_type_)];
149 break;
150 case HCI_PREAMBLE:
151
152 if (bytes_wanted_ == 0) {
153 size_t payload_size =
154 HciGetPacketLengthForType(hci_packet_type_, packet_.data());
155 if (payload_size == 0) {
156 OnPacketReady();
157 state_ = HCI_TYPE;
158 } else {
159 bytes_wanted_ = payload_size;
160 state_ = HCI_PAYLOAD;
161 }
162 }
163 break;
164 case HCI_PAYLOAD:
165 if (bytes_wanted_ == 0) {
166 OnPacketReady();
167 state_ = HCI_TYPE;
168 }
169 break;
170 }
171 return true;
172 }
173 } // namespace test_vendor_lib
174