xref: /aosp_15_r20/system/chre/chpp/test/packet_util.h (revision 84e339476a462649f82315436d70fd732297a399)
1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*84e33947SAndroid Build Coastguard Worker  *
4*84e33947SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*84e33947SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*84e33947SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*84e33947SAndroid Build Coastguard Worker  *
8*84e33947SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*84e33947SAndroid Build Coastguard Worker  *
10*84e33947SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*84e33947SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*84e33947SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*84e33947SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*84e33947SAndroid Build Coastguard Worker  * limitations under the License.
15*84e33947SAndroid Build Coastguard Worker  */
16*84e33947SAndroid Build Coastguard Worker 
17*84e33947SAndroid Build Coastguard Worker /**
18*84e33947SAndroid Build Coastguard Worker  * @file Utilities for working with raw CHPP packets in a test setting
19*84e33947SAndroid Build Coastguard Worker  */
20*84e33947SAndroid Build Coastguard Worker 
21*84e33947SAndroid Build Coastguard Worker #include <array>
22*84e33947SAndroid Build Coastguard Worker #include <cinttypes>
23*84e33947SAndroid Build Coastguard Worker #include <iostream>
24*84e33947SAndroid Build Coastguard Worker #include <vector>
25*84e33947SAndroid Build Coastguard Worker 
26*84e33947SAndroid Build Coastguard Worker #include <gtest/gtest.h>
27*84e33947SAndroid Build Coastguard Worker 
28*84e33947SAndroid Build Coastguard Worker #include "chpp/app.h"
29*84e33947SAndroid Build Coastguard Worker #include "chpp/crc.h"
30*84e33947SAndroid Build Coastguard Worker #include "chpp/transport.h"
31*84e33947SAndroid Build Coastguard Worker 
32*84e33947SAndroid Build Coastguard Worker namespace chpp::test {
33*84e33947SAndroid Build Coastguard Worker 
34*84e33947SAndroid Build Coastguard Worker // Note: the preamble is actually sent in the reverse byte order one might
35*84e33947SAndroid Build Coastguard Worker // expect (0x68 'h', 0x43 'C'); the simplification below assumes little endian
36*84e33947SAndroid Build Coastguard Worker constexpr uint16_t kPreamble =
37*84e33947SAndroid Build Coastguard Worker     (CHPP_PREAMBLE_BYTE_SECOND << 8) | CHPP_PREAMBLE_BYTE_FIRST;
38*84e33947SAndroid Build Coastguard Worker 
39*84e33947SAndroid Build Coastguard Worker struct ChppEmptyPacket {
40*84e33947SAndroid Build Coastguard Worker   uint16_t preamble;
41*84e33947SAndroid Build Coastguard Worker   ChppTransportHeader header;
42*84e33947SAndroid Build Coastguard Worker   ChppTransportFooter footer;
43*84e33947SAndroid Build Coastguard Worker } CHPP_PACKED_ATTR;
44*84e33947SAndroid Build Coastguard Worker 
45*84e33947SAndroid Build Coastguard Worker struct ChppResetPacket {
46*84e33947SAndroid Build Coastguard Worker   uint16_t preamble;
47*84e33947SAndroid Build Coastguard Worker   ChppTransportHeader header;
48*84e33947SAndroid Build Coastguard Worker   ChppTransportConfiguration config;
49*84e33947SAndroid Build Coastguard Worker   ChppTransportFooter footer;
50*84e33947SAndroid Build Coastguard Worker } CHPP_PACKED_ATTR;
51*84e33947SAndroid Build Coastguard Worker 
52*84e33947SAndroid Build Coastguard Worker struct ChppPacketPrefix {
53*84e33947SAndroid Build Coastguard Worker   uint16_t preamble;
54*84e33947SAndroid Build Coastguard Worker   ChppTransportHeader header;
55*84e33947SAndroid Build Coastguard Worker   uint8_t payload[1];  // Variable size per header.length
56*84e33947SAndroid Build Coastguard Worker } CHPP_PACKED_ATTR;
57*84e33947SAndroid Build Coastguard Worker 
58*84e33947SAndroid Build Coastguard Worker template <size_t kPayloadSize>
59*84e33947SAndroid Build Coastguard Worker struct ChppPacketWithPayload {
60*84e33947SAndroid Build Coastguard Worker   uint16_t preamble;
61*84e33947SAndroid Build Coastguard Worker   ChppTransportHeader header;
62*84e33947SAndroid Build Coastguard Worker   uint8_t payload[kPayloadSize];
63*84e33947SAndroid Build Coastguard Worker   ChppTransportFooter footer;
64*84e33947SAndroid Build Coastguard Worker } CHPP_PACKED_ATTR;
65*84e33947SAndroid Build Coastguard Worker 
66*84e33947SAndroid Build Coastguard Worker struct ChppPacketWithAppHeader {
67*84e33947SAndroid Build Coastguard Worker   uint16_t preamble;
68*84e33947SAndroid Build Coastguard Worker   ChppTransportHeader transportHeader;
69*84e33947SAndroid Build Coastguard Worker   ChppAppHeader appHeader;
70*84e33947SAndroid Build Coastguard Worker   uint8_t payload[];
71*84e33947SAndroid Build Coastguard Worker };
72*84e33947SAndroid Build Coastguard Worker 
73*84e33947SAndroid Build Coastguard Worker // Utilities for packet creation -----------------------------------------------
74*84e33947SAndroid Build Coastguard Worker 
75*84e33947SAndroid Build Coastguard Worker //! Computes the CRC of one of the complete packet types defined above
76*84e33947SAndroid Build Coastguard Worker template <typename PktType>
computeCrc(const PktType & pkt)77*84e33947SAndroid Build Coastguard Worker uint32_t computeCrc(const PktType &pkt) {
78*84e33947SAndroid Build Coastguard Worker   return chppCrc32(0, reinterpret_cast<const uint8_t *>(&pkt.header),
79*84e33947SAndroid Build Coastguard Worker                    sizeof(pkt) - sizeof(pkt.preamble) - sizeof(pkt.footer));
80*84e33947SAndroid Build Coastguard Worker }
81*84e33947SAndroid Build Coastguard Worker 
82*84e33947SAndroid Build Coastguard Worker ChppResetPacket generateResetPacket(uint8_t ackSeq = 0, uint8_t seq = 0);
83*84e33947SAndroid Build Coastguard Worker ChppResetPacket generateResetAckPacket(uint8_t ackSeq = 1, uint8_t seq = 0);
84*84e33947SAndroid Build Coastguard Worker ChppEmptyPacket generateEmptyPacket(uint8_t ackSeq = 1, uint8_t seq = 0,
85*84e33947SAndroid Build Coastguard Worker                                     uint8_t error = CHPP_TRANSPORT_ERROR_NONE);
86*84e33947SAndroid Build Coastguard Worker 
87*84e33947SAndroid Build Coastguard Worker //! Create an empty ACK packet for the given packet
88*84e33947SAndroid Build Coastguard Worker ChppEmptyPacket generateAck(const std::vector<uint8_t> &pkt);
89*84e33947SAndroid Build Coastguard Worker 
90*84e33947SAndroid Build Coastguard Worker //! Create a packet with payload of the given size. If a payload array is not
91*84e33947SAndroid Build Coastguard Worker //! provided, it is set to all-zeros.
92*84e33947SAndroid Build Coastguard Worker template <size_t kPayloadSize>
93*84e33947SAndroid Build Coastguard Worker ChppPacketWithPayload<kPayloadSize> generatePacketWithPayload(
94*84e33947SAndroid Build Coastguard Worker     uint8_t ackSeq = 0, uint8_t seq = 0,
95*84e33947SAndroid Build Coastguard Worker     const std::span<uint8_t, kPayloadSize> *payload = nullptr) {
96*84e33947SAndroid Build Coastguard Worker   // clang-format off
97*84e33947SAndroid Build Coastguard Worker   ChppPacketWithPayload<kPayloadSize> pkt = {
98*84e33947SAndroid Build Coastguard Worker     .preamble = kPreamble,
99*84e33947SAndroid Build Coastguard Worker     .header = {
100*84e33947SAndroid Build Coastguard Worker       .flags = CHPP_TRANSPORT_FLAG_FINISHED_DATAGRAM,
101*84e33947SAndroid Build Coastguard Worker       .packetCode = static_cast<uint8_t>(CHPP_ATTR_AND_ERROR_TO_PACKET_CODE(
102*84e33947SAndroid Build Coastguard Worker           CHPP_TRANSPORT_ATTR_NONE, CHPP_TRANSPORT_ERROR_NONE)),
103*84e33947SAndroid Build Coastguard Worker       .ackSeq = ackSeq,
104*84e33947SAndroid Build Coastguard Worker       .seq = seq,
105*84e33947SAndroid Build Coastguard Worker       .length = kPayloadSize,
106*84e33947SAndroid Build Coastguard Worker       .reserved = 0,
107*84e33947SAndroid Build Coastguard Worker     },
108*84e33947SAndroid Build Coastguard Worker   };
109*84e33947SAndroid Build Coastguard Worker   // clang-format on
110*84e33947SAndroid Build Coastguard Worker   if (payload != nullptr) {
111*84e33947SAndroid Build Coastguard Worker     std::memcpy(pkt.payload, payload->data(), sizeof(pkt.payload));
112*84e33947SAndroid Build Coastguard Worker   }
113*84e33947SAndroid Build Coastguard Worker   pkt.footer.checksum = computeCrc(pkt);
114*84e33947SAndroid Build Coastguard Worker   return pkt;
115*84e33947SAndroid Build Coastguard Worker }
116*84e33947SAndroid Build Coastguard Worker 
117*84e33947SAndroid Build Coastguard Worker // Utilities for packet parsing ------------------------------------------------
118*84e33947SAndroid Build Coastguard Worker 
asEmptyPacket(const std::vector<uint8_t> & pkt)119*84e33947SAndroid Build Coastguard Worker inline const ChppEmptyPacket &asEmptyPacket(const std::vector<uint8_t> &pkt) {
120*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(pkt.size(), sizeof(ChppEmptyPacket));
121*84e33947SAndroid Build Coastguard Worker   return *reinterpret_cast<const ChppEmptyPacket *>(pkt.data());
122*84e33947SAndroid Build Coastguard Worker }
123*84e33947SAndroid Build Coastguard Worker 
asResetPacket(const std::vector<uint8_t> & pkt)124*84e33947SAndroid Build Coastguard Worker inline const ChppResetPacket &asResetPacket(const std::vector<uint8_t> &pkt) {
125*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(pkt.size(), sizeof(ChppResetPacket));
126*84e33947SAndroid Build Coastguard Worker   return *reinterpret_cast<const ChppResetPacket *>(pkt.data());
127*84e33947SAndroid Build Coastguard Worker }
128*84e33947SAndroid Build Coastguard Worker 
asChpp(const std::vector<uint8_t> & pkt)129*84e33947SAndroid Build Coastguard Worker inline const ChppPacketPrefix &asChpp(const std::vector<uint8_t> &pkt) {
130*84e33947SAndroid Build Coastguard Worker   EXPECT_GE(pkt.size(), sizeof(ChppEmptyPacket));
131*84e33947SAndroid Build Coastguard Worker   return *reinterpret_cast<const ChppPacketPrefix *>(pkt.data());
132*84e33947SAndroid Build Coastguard Worker }
133*84e33947SAndroid Build Coastguard Worker 
getHeader(const std::vector<uint8_t> & pkt)134*84e33947SAndroid Build Coastguard Worker inline const ChppTransportHeader &getHeader(const std::vector<uint8_t> &pkt) {
135*84e33947SAndroid Build Coastguard Worker   static_assert(CHPP_PREAMBLE_LEN_BYTES == sizeof(uint16_t));
136*84e33947SAndroid Build Coastguard Worker   EXPECT_GE(pkt.size(), sizeof(uint16_t) + sizeof(ChppTransportHeader));
137*84e33947SAndroid Build Coastguard Worker   return *reinterpret_cast<const ChppTransportHeader *>(&pkt[sizeof(uint16_t)]);
138*84e33947SAndroid Build Coastguard Worker }
139*84e33947SAndroid Build Coastguard Worker 
asApp(const std::vector<uint8_t> & pkt)140*84e33947SAndroid Build Coastguard Worker inline const ChppPacketWithAppHeader &asApp(const std::vector<uint8_t> &pkt) {
141*84e33947SAndroid Build Coastguard Worker   EXPECT_GE(pkt.size(),
142*84e33947SAndroid Build Coastguard Worker             sizeof(ChppPacketWithAppHeader) + sizeof(ChppTransportFooter));
143*84e33947SAndroid Build Coastguard Worker   return *reinterpret_cast<const ChppPacketWithAppHeader *>(pkt.data());
144*84e33947SAndroid Build Coastguard Worker }
145*84e33947SAndroid Build Coastguard Worker 
146*84e33947SAndroid Build Coastguard Worker // Utilities for debugging -----------------------------------------------------
147*84e33947SAndroid Build Coastguard Worker 
148*84e33947SAndroid Build Coastguard Worker const char *appErrorCodeToStr(uint8_t error);
149*84e33947SAndroid Build Coastguard Worker const char *appMessageTypeToStr(uint8_t type);
150*84e33947SAndroid Build Coastguard Worker const char *handleToStr(uint8_t handle);
151*84e33947SAndroid Build Coastguard Worker const char *packetAttrToStr(uint8_t attr);
152*84e33947SAndroid Build Coastguard Worker const char *transportErrorToStr(uint8_t error);
153*84e33947SAndroid Build Coastguard Worker 
154*84e33947SAndroid Build Coastguard Worker //! Tuned for outputting a raw binary buffer (e.g. payload or full packet)
155*84e33947SAndroid Build Coastguard Worker void dumpRaw(std::ostream &os, const void *ptr, size_t len);
156*84e33947SAndroid Build Coastguard Worker 
157*84e33947SAndroid Build Coastguard Worker void dumpPreamble(std::ostream &os, uint16_t preamble);
158*84e33947SAndroid Build Coastguard Worker void dumpHeader(std::ostream &os, const ChppTransportHeader &hdr);
159*84e33947SAndroid Build Coastguard Worker void dumpConfig(std::ostream &os, const ChppTransportConfiguration &cfg);
160*84e33947SAndroid Build Coastguard Worker 
161*84e33947SAndroid Build Coastguard Worker template <typename PktType>
dumpFooter(std::ostream & os,const PktType & pkt)162*84e33947SAndroid Build Coastguard Worker void dumpFooter(std::ostream &os, const PktType &pkt) {
163*84e33947SAndroid Build Coastguard Worker   os << "CRC: 0x" << std::hex << pkt.footer.checksum;
164*84e33947SAndroid Build Coastguard Worker   uint32_t computed = computeCrc(pkt);
165*84e33947SAndroid Build Coastguard Worker   if (pkt.footer.checksum != computed) {
166*84e33947SAndroid Build Coastguard Worker     os << " (invalid, expected " << computed << ")";
167*84e33947SAndroid Build Coastguard Worker   } else {
168*84e33947SAndroid Build Coastguard Worker     os << " (ok)";
169*84e33947SAndroid Build Coastguard Worker   }
170*84e33947SAndroid Build Coastguard Worker   os << std::endl;
171*84e33947SAndroid Build Coastguard Worker }
172*84e33947SAndroid Build Coastguard Worker 
173*84e33947SAndroid Build Coastguard Worker void dumpEmptyPacket(std::ostream &os, const ChppEmptyPacket &pkt);
174*84e33947SAndroid Build Coastguard Worker void dumpResetPacket(std::ostream &os, const ChppResetPacket &pkt);
175*84e33947SAndroid Build Coastguard Worker void dumpPacket(std::ostream &os, const ChppPacketPrefix &pkt);
176*84e33947SAndroid Build Coastguard Worker 
177*84e33947SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const ChppEmptyPacket &pkt);
178*84e33947SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const ChppResetPacket &pkt);
179*84e33947SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const ChppPacketPrefix &pkt);
180*84e33947SAndroid Build Coastguard Worker 
181*84e33947SAndroid Build Coastguard Worker // Utilities for gtest packet checking -----------------------------------------
182*84e33947SAndroid Build Coastguard Worker 
183*84e33947SAndroid Build Coastguard Worker //! Confirms that the supplied packet has a valid preamble, CRC, length, etc.,
184*84e33947SAndroid Build Coastguard Worker //! raising a gtest failure (via EXPECT_*) if not
185*84e33947SAndroid Build Coastguard Worker void checkPacketValidity(std::vector<uint8_t> &received);
186*84e33947SAndroid Build Coastguard Worker 
187*84e33947SAndroid Build Coastguard Worker // These return true if the packets are the same, false otherwise
188*84e33947SAndroid Build Coastguard Worker 
189*84e33947SAndroid Build Coastguard Worker bool comparePacketHeader(const ChppTransportHeader &rx,
190*84e33947SAndroid Build Coastguard Worker                          const ChppTransportHeader &expected);
191*84e33947SAndroid Build Coastguard Worker 
192*84e33947SAndroid Build Coastguard Worker bool comparePacket(const std::vector<uint8_t> &received,
193*84e33947SAndroid Build Coastguard Worker                    const ChppEmptyPacket &expected);
194*84e33947SAndroid Build Coastguard Worker bool comparePacket(const std::vector<uint8_t> &received,
195*84e33947SAndroid Build Coastguard Worker                    const ChppResetPacket &expected);
196*84e33947SAndroid Build Coastguard Worker 
197*84e33947SAndroid Build Coastguard Worker }  // namespace chpp::test