blob: 7792f4f68f52a4997848e95b588d7e31cc8f0cfb [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/devices/power/drivers/fusb302/usb-pd-message.h"
#include <cstdint>
#include <type_traits>
#include <utility>
#include <zxtest/zxtest.h>
#include "src/devices/power/drivers/fusb302/usb-pd-defs.h"
#include "src/devices/power/drivers/fusb302/usb-pd-message-type.h"
namespace usb_pd {
namespace {
static_assert(std::is_trivially_destructible_v<MessageId>);
static_assert(std::is_trivially_destructible_v<Header>);
static_assert(std::is_trivially_destructible_v<Message>);
TEST(MessageIdTest, RoundTripToUint8t) {
uint8_t message_id_bits = 5;
auto cast1_message_id = static_cast<MessageId>(message_id_bits);
EXPECT_EQ(message_id_bits, static_cast<uint8_t>(cast1_message_id));
MessageId cast2_message_id(message_id_bits);
EXPECT_EQ(message_id_bits, static_cast<uint8_t>(cast2_message_id));
}
TEST(MessageIdTest, DefaultConstructor) {
MessageId message_id;
EXPECT_EQ(0u, static_cast<uint8_t>(message_id));
}
TEST(MessageIdTest, CopyConstructor) {
MessageId source_id = static_cast<MessageId>(5);
MessageId copied_id = source_id;
EXPECT_EQ(5u, static_cast<uint8_t>(copied_id));
}
TEST(MessageIdTest, CopyAssignment) {
MessageId copied_id(3);
MessageId source_id(5);
copied_id = source_id;
EXPECT_EQ(5u, static_cast<uint8_t>(copied_id));
}
TEST(MessageIdTest, Equality) {
MessageId three(3);
MessageId five(5);
// This test uses EXPECT_TRUE() so that the operator use is explicit.
EXPECT_TRUE(three == MessageId(three));
EXPECT_TRUE(MessageId(five) == five);
EXPECT_TRUE(three != MessageId(five));
}
TEST(MessageIdTest, NextIncrements) {
MessageId message_id;
message_id = message_id.Next();
EXPECT_EQ(1u, static_cast<uint8_t>(message_id));
message_id = message_id.Next();
EXPECT_EQ(2u, static_cast<uint8_t>(message_id));
}
TEST(MessageIdTest, NextRollsOver) {
MessageId message_id(6);
message_id = message_id.Next();
EXPECT_EQ(7u, static_cast<uint8_t>(message_id));
message_id = message_id.Next();
EXPECT_EQ(0u, static_cast<uint8_t>(message_id));
}
TEST(MessageIdTest, Reset) {
MessageId message_id(5);
message_id.Reset();
EXPECT_EQ(0u, static_cast<uint8_t>(message_id));
}
TEST(HeaderTest, CreateFromBytes) {
Header header = Header::CreateFromBytes(0xa1, 0x11);
static constexpr std::pair<uint8_t, uint8_t> expected_bytes = {0xa1, 0x11};
EXPECT_EQ(expected_bytes, header.bytes());
}
TEST(HeaderTest, MessageTypeGoodCrc) {
Header header = Header::CreateFromBytes(0x00, 0x00);
header.set_message_type(MessageType::kGoodCrc);
EXPECT_EQ(MessageType::kGoodCrc, header.message_type());
static constexpr std::pair<uint8_t, uint8_t> expected_bytes = {0b0000'0001, 0b0000'0000};
EXPECT_EQ(expected_bytes, header.bytes());
}
TEST(HeaderTest, MessageTypeSourceCapabilties) {
Header header = Header::CreateFromBytes(0x00, 0x00);
header.set_data_object_count(5);
header.set_message_type(MessageType::kSourceCapabilities);
EXPECT_EQ(MessageType::kSourceCapabilities, header.message_type());
static constexpr std::pair<uint8_t, uint8_t> expected_bytes = {0b0000'0001, 0b0101'0000};
EXPECT_EQ(expected_bytes, header.bytes());
}
TEST(HeaderTest, MessageId) {
Header header = Header::CreateFromBytes(0x00, 0x00);
header.set_message_id(MessageId(0b101));
EXPECT_EQ(MessageId(0b101), header.message_id());
static constexpr std::pair<uint8_t, uint8_t> expected_bytes = {0b0000'0000, 0b0000'1010};
EXPECT_EQ(expected_bytes, header.bytes());
}
TEST(HeaderTest, SourceCapabilitiesOneObject) {
// From the USB Type C ports of the Framework Gen 12 laptop.
Header header = Header::CreateFromBytes(0xa1, 0x11);
EXPECT_EQ(false, header.is_extended());
EXPECT_EQ(1, header.data_object_count());
EXPECT_EQ(0u, static_cast<uint8_t>(header.message_id()));
EXPECT_EQ(PowerRole::kSource, header.power_role());
EXPECT_EQ(SpecRevision::kRev3, header.spec_revision());
EXPECT_EQ(DataRole::kDownstreamFacingPort, header.data_role());
EXPECT_EQ(MessageType::kSourceCapabilities, header.message_type());
EXPECT_EQ(usb_pd::MessageId(0), header.message_id());
EXPECT_EQ(4, header.payload_bytes());
EXPECT_EQ(6, header.message_bytes());
}
TEST(HeaderConcreteParsingTest, GoodCrcFromSink) {
Header header = Header::CreateFromBytes(0x41, 0x00);
EXPECT_EQ(PowerRole::kSink, header.power_role());
EXPECT_EQ(SpecRevision::kRev2, header.spec_revision());
EXPECT_EQ(DataRole::kUpstreamFacingPort, header.data_role());
EXPECT_EQ(MessageType::kGoodCrc, header.message_type());
EXPECT_EQ(usb_pd::MessageId(0), header.message_id());
EXPECT_EQ(0, header.data_object_count());
}
TEST(HeaderConcreteParsingTest, RequestFromSink) {
Header header = Header::CreateFromBytes(0x82, 0x10);
EXPECT_EQ(PowerRole::kSink, header.power_role());
EXPECT_EQ(SpecRevision::kRev3, header.spec_revision());
EXPECT_EQ(DataRole::kUpstreamFacingPort, header.data_role());
EXPECT_EQ(MessageType::kRequestPower, header.message_type());
EXPECT_EQ(usb_pd::MessageId(0), header.message_id());
EXPECT_EQ(1, header.data_object_count());
}
TEST(HeaderConcreteParsingTest, GoodCrcFromSourceMessage0) {
Header header = Header::CreateFromBytes(0x61, 0x01);
EXPECT_EQ(PowerRole::kSource, header.power_role());
EXPECT_EQ(SpecRevision::kRev2, header.spec_revision());
EXPECT_EQ(DataRole::kDownstreamFacingPort, header.data_role());
EXPECT_EQ(MessageType::kGoodCrc, header.message_type());
EXPECT_EQ(usb_pd::MessageId(0), header.message_id());
EXPECT_EQ(0, header.data_object_count());
}
TEST(HeaderConcreteParsingTest, GoodCrcFromSourceMessage1) {
Header header = Header::CreateFromBytes(0x61, 0x03);
EXPECT_EQ(PowerRole::kSource, header.power_role());
EXPECT_EQ(SpecRevision::kRev2, header.spec_revision());
EXPECT_EQ(DataRole::kDownstreamFacingPort, header.data_role());
EXPECT_EQ(MessageType::kGoodCrc, header.message_type());
EXPECT_EQ(usb_pd::MessageId(1), header.message_id());
EXPECT_EQ(0, header.data_object_count());
}
TEST(HeaderConcreteParsingTest, AcceptFromSource) {
Header header = Header::CreateFromBytes(0xa3, 0x01);
EXPECT_EQ(PowerRole::kSource, header.power_role());
EXPECT_EQ(SpecRevision::kRev3, header.spec_revision());
EXPECT_EQ(DataRole::kDownstreamFacingPort, header.data_role());
EXPECT_EQ(MessageType::kAccept, header.message_type());
EXPECT_EQ(usb_pd::MessageId(0), header.message_id());
EXPECT_EQ(0, header.data_object_count());
}
TEST(HeaderConcreteParsingTest, SoftResetFromSource) {
Header header = Header::CreateFromBytes(0xad, 0x01);
EXPECT_EQ(PowerRole::kSource, header.power_role());
EXPECT_EQ(SpecRevision::kRev3, header.spec_revision());
EXPECT_EQ(DataRole::kDownstreamFacingPort, header.data_role());
EXPECT_EQ(MessageType::kSoftReset, header.message_type());
EXPECT_EQ(usb_pd::MessageId(0), header.message_id());
EXPECT_EQ(0, header.data_object_count());
}
TEST(HeaderConcreteParsingTest, GetSourceCapabilitiesFromSink) {
Header header = Header::CreateFromBytes(0x47, 0x00);
EXPECT_EQ(PowerRole::kSink, header.power_role());
EXPECT_EQ(SpecRevision::kRev2, header.spec_revision());
EXPECT_EQ(DataRole::kUpstreamFacingPort, header.data_role());
EXPECT_EQ(MessageType::kGetSourceCapabilities, header.message_type());
EXPECT_EQ(usb_pd::MessageId(0), header.message_id());
EXPECT_EQ(0, header.data_object_count());
}
TEST(MessageTest, SourceCapabilitiesOneObject) {
// From the USB Type C ports of the Framework Gen 12 laptop.
Header header = Header::CreateFromBytes(0xa1, 0x11);
const uint32_t kDataObjects[] = {0x2701912c};
Message message(header, kDataObjects);
EXPECT_EQ(MessageType::kSourceCapabilities, message.header().message_type());
ASSERT_EQ(1, message.data_objects().size());
EXPECT_EQ(0x2701912c, message.data_objects()[0]);
}
TEST(MessageTest, SourceCapabilitiesMaximumObjects) {
// From Anker 30W Nano 511 model A2337.
Header header = Header::CreateFromBytes(0xa1, 0x71);
const uint32_t kDataObjects[] = {0x0a01912c, 0x0002d12c, 0x0003c0fa, 0x0004b0c8,
0x00064096, 0xc8dc213c, 0xc9402128};
Message message(header, kDataObjects);
EXPECT_EQ(MessageType::kSourceCapabilities, message.header().message_type());
ASSERT_EQ(7, message.data_objects().size());
EXPECT_EQ(0x0a01912c, message.data_objects()[0]);
EXPECT_EQ(0xc9402128, message.data_objects()[6]);
}
TEST(MessageTest, GetSourceCapabilities) {
Message message(MessageType::kGetSourceCapabilities, MessageId(0), PowerRole::kSink,
SpecRevision::kRev2, DataRole::kUpstreamFacingPort, {});
static constexpr std::pair<uint8_t, uint8_t> expected_bytes = {0x47, 0x00};
EXPECT_EQ(expected_bytes, message.header().bytes());
}
} // namespace
} // namespace usb_pd