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