blob: c0da777e0a21f90b93aaec3507ef0e4323a6caad [file] [log] [blame]
// Copyright 2019 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 "bt-hci-mediatek.h"
#include <lib/mock-function/mock-function.h>
#include <lib/mock-sdio/mock-sdio.h>
#include <zxtest/zxtest.h>
namespace bluetooth {
class BtHciMediatekTest : public BtHciMediatek {
public:
struct CardTxnResult {
zx_status_t status;
uint32_t data;
};
struct CardBlockTxnResult {
zx_status_t status;
const uint8_t* data;
size_t size;
};
BtHciMediatekTest(const ddk::SdioProtocolClient& sdio, size_t fw_part_max_size = 0)
: BtHciMediatek(nullptr, sdio, zx::port(), fw_part_max_size) {}
mock_function::MockFunction<CardTxnResult, uint32_t>& mock_CardRead32() {
return mock_read32_;
}
mock_function::MockFunction<zx_status_t, uint32_t, uint32_t>& mock_CardWrite32() {
return mock_write32_;
}
mock_function::MockFunction<CardTxnResult>& mock_CardRecvPacket() {
return mock_recv_packet_;
}
mock_function::MockFunction<zx_status_t>& mock_CardReset() {
return mock_reset_;
}
mock_function::MockFunction<CardTxnResult>& mock_CardGetHwVersion() {
return mock_get_hw_version_;
}
mock_function::MockFunction<CardBlockTxnResult, FirmwarePartMode>& mock_CardSendFirmwarePart() {
return mock_send_firmware_part_;
}
void VerifyAll() {
mock_read32_.VerifyAndClear();
mock_write32_.VerifyAndClear();
mock_recv_packet_.VerifyAndClear();
mock_reset_.VerifyAndClear();
mock_get_hw_version_.VerifyAndClear();
mock_send_firmware_part_.VerifyAndClear();
}
zx_status_t CardRecvPacket(uint32_t* size) override {
if (mock_recv_packet_.HasExpectations()) {
CardTxnResult result = mock_recv_packet_.Call();
*size = result.data;
return result.status;
} else {
return BtHciMediatek::CardRecvPacket(size);
}
}
zx_status_t CardSendFirmwarePart(zx_handle_t vmo, uint8_t* buffer, const uint8_t* fw_data,
size_t size, FirmwarePartMode mode) override {
if (mock_send_firmware_part_.HasExpectations()) {
CardBlockTxnResult result = mock_send_firmware_part_.Call(mode);
CardSendFirmwarePartHelper(result, fw_data, size);
return result.status;
} else {
return BtHciMediatek::CardSendFirmwarePart(vmo, buffer, fw_data, size, mode);
}
}
private:
zx_status_t CardRead32(uint32_t address, uint32_t* value) override {
CardTxnResult result = mock_read32_.Call(address);
*value = result.data;
return result.status;
}
zx_status_t CardWrite32(uint32_t address, uint32_t value) override {
return mock_write32_.Call(address, value);
}
zx_status_t CardReset() override {
return mock_reset_.Call();
}
zx_status_t CardGetHwVersion(uint32_t* version) override {
CardTxnResult result = mock_get_hw_version_.Call();
*version = result.data;
return result.status;
}
void CardSendFirmwarePartHelper(const CardBlockTxnResult& result, const uint8_t* fw_data,
size_t size) {
ASSERT_EQ(result.size, size);
EXPECT_BYTES_EQ(result.data, fw_data, result.size);
}
mock_function::MockFunction<CardTxnResult, uint32_t> mock_read32_;
mock_function::MockFunction<zx_status_t, uint32_t, uint32_t> mock_write32_;
mock_function::MockFunction<CardTxnResult> mock_recv_packet_;
mock_function::MockFunction<zx_status_t> mock_reset_;
mock_function::MockFunction<CardTxnResult> mock_get_hw_version_;
mock_function::MockFunction<CardBlockTxnResult, FirmwarePartMode> mock_send_firmware_part_;
};
TEST(BtHciMediatekTest, TestCardRecvPacket) {
mock_sdio::MockSdio sdio;
BtHciMediatekTest test(ddk::SdioProtocolClient(sdio.GetProto()));
test.mock_CardRead32().ExpectCall({ZX_OK, 0xabcd1236}, 0x10);
test.mock_CardWrite32().ExpectCall(ZX_OK, 0x10, 0x00001232);
uint32_t size = 0;
EXPECT_OK(test.CardRecvPacket(&size));
EXPECT_EQ(0xabcd, size);
test.VerifyAll();
// Test a timeout condition.
test.mock_CardRead32()
.ExpectCall({ZX_OK, 0xabcd0000}, 0x10)
.ExpectCall({ZX_OK, 0x00000000}, 0x10)
.ExpectCall({ZX_OK, 0x00000000}, 0x10)
.ExpectCall({ZX_OK, 0x00000002}, 0x10)
.ExpectCall({ZX_OK, 0x12340000}, 0x10)
.ExpectCall({ZX_OK, 0x00000002}, 0x10);
test.mock_CardWrite32().ExpectNoCall();
EXPECT_EQ(ZX_ERR_TIMED_OUT, test.CardRecvPacket(&size));
test.VerifyAll();
}
TEST(BtHciMediatekTest, TestCardSendVendorPacketCmd) {
mock_sdio::MockSdio sdio;
BtHciMediatekTest test(ddk::SdioProtocolClient(sdio.GetProto()));
fbl::Vector<uint8_t> write_data = {0x10, 0x00, 0x00, 0x00,
0x01, 0xcd, 0xfc, 0x08,
0xe5, 0xd5, 0x4d, 0x4d,
0x4d, 0xad, 0x47, 0xd0};
fbl::Vector<uint8_t> read_data = {0x14, 0x00, 0x00, 0x00,
0x32, 0xbf, 0x9c, 0x81,
0x70, 0xdd, 0x9a, 0x68,
0xf0, 0x36, 0x06, 0x49,
0x7c, 0x7b, 0x83, 0x21};
uint8_t expected_read_packet[16];
memcpy(expected_read_packet, read_data.get() + 4, read_data.size() - 4);
uint8_t packet[32];
size_t size = write_data.size() - 8;
memcpy(packet, write_data.get() + 8, size);
sdio.ExpectFifoWrite(2, 0x18, std::move(write_data), false);
test.mock_CardRecvPacket().ExpectCall({ZX_OK, static_cast<uint32_t>(read_data.size())});
sdio.ExpectFifoRead(2, 0x1c, std::move(read_data), true);
EXPECT_OK(test.CardSendVendorPacket(1, 0xcd, packet, &size, sizeof(packet)));
ASSERT_EQ(sizeof(expected_read_packet), size);
EXPECT_BYTES_EQ(expected_read_packet, packet, sizeof(expected_read_packet));
test.VerifyAll();
sdio.VerifyAndClear();
}
TEST(BtHciMediatekTest, TestCardSendVendorPacketAcl) {
mock_sdio::MockSdio sdio;
BtHciMediatekTest test(ddk::SdioProtocolClient(sdio.GetProto()));
fbl::Vector<uint8_t> write_data = {0x19, 0x00, 0x00, 0x00,
0x02, 0xab, 0xfc, 0x10, 0x00,
0x87, 0xae, 0x01, 0x46,
0x3c, 0xd9, 0xd7, 0x68,
0x8b, 0x07, 0x9b, 0xc8,
0xb1, 0xf3, 0x99, 0x13};
fbl::Vector<uint8_t> read_data = {0x08, 0x00, 0x00, 0x00,
0xc6, 0x7b, 0x1a, 0x84};
uint8_t expected_read_packet[4];
memcpy(expected_read_packet, read_data.get() + 4, read_data.size() - 4);
uint8_t packet[32];
size_t size = write_data.size() - 9;
memcpy(packet, write_data.get() + 9, size);
sdio.ExpectFifoWrite(2, 0x18, std::move(write_data), false);
test.mock_CardRecvPacket().ExpectCall({ZX_OK, static_cast<uint32_t>(read_data.size())});
sdio.ExpectFifoRead(2, 0x1c, std::move(read_data), true);
EXPECT_OK(test.CardSendVendorPacket(2, 0xab, packet, &size, sizeof(packet)));
ASSERT_EQ(sizeof(expected_read_packet), size);
EXPECT_BYTES_EQ(expected_read_packet, packet, sizeof(expected_read_packet));
test.VerifyAll();
sdio.VerifyAndClear();
}
TEST(BtHciMediatekTest, TestCardSendVendorPacketEdgeCases) {
mock_sdio::MockSdio sdio;
BtHciMediatekTest test(ddk::SdioProtocolClient(sdio.GetProto()));
fbl::Vector<uint8_t> write_data = {0x0c, 0x00, 0x00, 0x00,
0x01, 0xef, 0xfc, 0x04,
0x02, 0xe6, 0x55, 0xa6};
fbl::Vector<uint8_t> read_data = {0x04, 0x00, 0x00, 0x00};
uint8_t packet[12];
size_t size = write_data.size() - 8;
memcpy(packet, write_data.get() + 8, size);
sdio.ExpectFifoWrite(2, 0x18, std::move(write_data), false);
test.mock_CardRecvPacket().ExpectCall({ZX_OK, static_cast<uint32_t>(read_data.size())});
sdio.ExpectFifoRead(2, 0x1c, std::move(read_data), true);
EXPECT_OK(test.CardSendVendorPacket(1, 0xef, packet, &size, sizeof(packet)));
ASSERT_EQ(0, size);
test.VerifyAll();
sdio.VerifyAndClear();
}
TEST(BtHciMediatekTest, TestCardSendVendorPacketFail) {
mock_sdio::MockSdio sdio;
BtHciMediatekTest test(ddk::SdioProtocolClient(sdio.GetProto()));
// Received packet is shorter than the SDIO header.
fbl::Vector<uint8_t> write_data = {0x0c, 0x00, 0x00, 0x00,
0x01, 0x00, 0xfc, 0x04,
0x31, 0x7b, 0xc0, 0x78};
uint8_t packet[12];
size_t size = write_data.size() - 8;
memcpy(packet, write_data.get() + 8, size);
sdio.ExpectFifoWrite(2, 0x18, std::move(write_data), false);
test.mock_CardRecvPacket().ExpectCall({ZX_OK, 3});
EXPECT_NE(ZX_OK, test.CardSendVendorPacket(1, 0x00, packet, &size, sizeof(packet)));
test.VerifyAll();
sdio.VerifyAndClear();
// Received packet does not fit in the provided buffer.
write_data = {0x0c, 0x00, 0x00, 0x00,
0x01, 0x00, 0xfc, 0x04,
0x25, 0xce, 0xd4, 0xf2};
size = write_data.size() - 8;
memcpy(packet, write_data.get() + 8, size);
sdio.ExpectFifoWrite(2, 0x18, std::move(write_data), false);
test.mock_CardRecvPacket().ExpectCall({ZX_OK, sizeof(packet) + 5});
EXPECT_NE(ZX_OK, test.CardSendVendorPacket(1, 0x00, packet, &size, sizeof(packet)));
test.VerifyAll();
sdio.VerifyAndClear();
// Received packet size field doesn't match size field from CHISR register.
write_data = {0x0c, 0x00, 0x00, 0x00,
0x01, 0x00, 0xfc, 0x04,
0xcd, 0x9b, 0x46, 0xfc};
fbl::Vector<uint8_t> read_data = {0x06, 0x00, 0x00, 0x00,
0xa3, 0x2f, 0x2c, 0xf0};
size = write_data.size() - 8;
memcpy(packet, write_data.get() + 8, size);
sdio.ExpectFifoWrite(2, 0x18, std::move(write_data), false);
test.mock_CardRecvPacket().ExpectCall({ZX_OK, static_cast<uint32_t>(read_data.size())});
sdio.ExpectFifoRead(2, 0x1c, std::move(read_data), true);
EXPECT_NE(ZX_OK, test.CardSendVendorPacket(1, 0x00, packet, &size, sizeof(packet)));
test.VerifyAll();
sdio.VerifyAndClear();
}
TEST(BtHciMediatekTest, TestCardSendFirmwarePart) {
constexpr uint8_t kExpectedResponse[] = {0x0c, 0x00, 0x00, 0x00,
0x04, 0xe4, 0x05, 0x02,
0x01, 0x01, 0x00, 0x00};
mock_sdio::MockSdio sdio;
BtHciMediatekTest test(ddk::SdioProtocolClient(sdio.GetProto()));
fbl::Vector<uint8_t> write_data = {0x2e, 0x00, 0x00, 0x00, // SDIO header
0x02, 0x6f, 0xfc, 0x25, 0x00, // Vendor header
0x01, 0x01, 0x21, 0x00, 0x01, // STP header
0xc9, 0xad, 0x54, 0x57, 0x36, 0xe3, 0x02, 0x9b, // Payload
0x71, 0x93, 0x0e, 0x64, 0xfb, 0xe4, 0x5c, 0x94,
0xd5, 0xae, 0x0b, 0x37, 0x45, 0xbf, 0x30, 0x54,
0x52, 0x29, 0x2f, 0x27, 0xa4, 0x74, 0x4f, 0xd9};
zx::vmo vmo;
fzl::VmoMapper mapper;
ASSERT_OK(
mapper.CreateAndMap(write_data.size(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &vmo));
uint8_t* buffer = reinterpret_cast<uint8_t*>(mapper.start());
uint8_t fw_data[32];
size_t fw_data_size = write_data.size() - 14;
memcpy(fw_data, write_data.get() + 14, fw_data_size);
fbl::Vector<uint8_t> read_data;
for (size_t i = 0; i < sizeof(kExpectedResponse); i++) {
read_data.push_back(kExpectedResponse[i]);
}
sdio.ExpectFifoWrite(2, 0x18, std::move(write_data), false);
test.mock_CardRecvPacket().ExpectCall({ZX_OK, static_cast<uint32_t>(read_data.size())});
sdio.ExpectFifoRead(2, 0x1c, std::move(read_data), true);
EXPECT_OK(test.CardSendFirmwarePart(vmo.get(), buffer, fw_data, fw_data_size,
BtHciMediatek::kFirmwarePartFirst));
test.VerifyAll();
sdio.VerifyAndClear();
write_data = {0x2e, 0x00, 0x00, 0x00,
0x02, 0x6f, 0xfc, 0x25, 0x00,
0x01, 0x01, 0x21, 0x00, 0x02,
0xe9, 0x39, 0x18, 0x18, 0x6a, 0x3b, 0xd7, 0x1a,
0x94, 0xca, 0xd2, 0x93, 0xdc, 0x34, 0xbb, 0x86,
0x4a, 0x7d, 0x48, 0x48, 0x6b, 0xfd, 0xc0, 0xa6,
0xb6, 0x01, 0xe1, 0xec, 0x3f, 0xac, 0x57, 0x2f};
fw_data_size = write_data.size() - 14;
memcpy(fw_data, write_data.get() + 14, fw_data_size);
for (size_t i = 0; i < sizeof(kExpectedResponse); i++) {
read_data.push_back(kExpectedResponse[i]);
}
sdio.ExpectFifoWrite(2, 0x18, std::move(write_data), false);
test.mock_CardRecvPacket().ExpectCall({ZX_OK, static_cast<uint32_t>(read_data.size())});
sdio.ExpectFifoRead(2, 0x1c, std::move(read_data), true);
EXPECT_OK(test.CardSendFirmwarePart(vmo.get(), buffer, fw_data, fw_data_size,
BtHciMediatek::kFirmwarePartContinue));
test.VerifyAll();
sdio.VerifyAndClear();
write_data = {0x16, 0x00, 0x00, 0x00,
0x02, 0x6f, 0xfc, 0x0d, 0x00,
0x01, 0x01, 0x09, 0x00, 0x03,
0x90, 0x8a, 0x05, 0xd6, 0x68, 0x5c, 0x39, 0x81};
fw_data_size = write_data.size() - 14;
memcpy(fw_data, write_data.get() + 14, fw_data_size);
for (size_t i = 0; i < sizeof(kExpectedResponse); i++) {
read_data.push_back(kExpectedResponse[i]);
}
sdio.ExpectFifoWrite(2, 0x18, std::move(write_data), false);
test.mock_CardRecvPacket().ExpectCall({ZX_OK, static_cast<uint32_t>(read_data.size())});
sdio.ExpectFifoRead(2, 0x1c, std::move(read_data), true);
EXPECT_OK(test.CardSendFirmwarePart(vmo.get(), buffer, fw_data, fw_data_size,
BtHciMediatek::kFirmwarePartLast));
test.VerifyAll();
sdio.VerifyAndClear();
}
TEST(BtHciMediatekTest, TestCardSendFirmwarePartFail) {
mock_sdio::MockSdio sdio;
BtHciMediatekTest test(ddk::SdioProtocolClient(sdio.GetProto()));
fbl::Vector<uint8_t> write_data = {0x16, 0x00, 0x00, 0x00,
0x02, 0x6f, 0xfc, 0x0d, 0x00,
0x01, 0x01, 0x09, 0x00, 0x01,
0x5e, 0xe0, 0xb5, 0x7e, 0xf8, 0x90, 0x46, 0xa3};
zx::vmo vmo;
fzl::VmoMapper mapper;
ASSERT_OK(
mapper.CreateAndMap(write_data.size(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &vmo));
uint8_t* buffer = reinterpret_cast<uint8_t*>(mapper.start());
uint8_t fw_data[8];
size_t fw_data_size = write_data.size() - 14;
memcpy(fw_data, write_data.get() + 14, fw_data_size);
sdio.ExpectFifoWrite(2, 0x18, std::move(write_data), false);
test.mock_CardRecvPacket().ExpectCall({ZX_OK, 13});
EXPECT_NE(ZX_OK, test.CardSendFirmwarePart(vmo.get(), buffer, fw_data, fw_data_size,
BtHciMediatek::kFirmwarePartFirst));
test.VerifyAll();
sdio.VerifyAndClear();
write_data = {0x16, 0x00, 0x00, 0x00,
0x02, 0x6f, 0xfc, 0x0d, 0x00,
0x01, 0x01, 0x09, 0x00, 0x03,
0x7c, 0x4b, 0x8b, 0xd2, 0x73, 0x0d, 0x72, 0x8e};
fw_data_size = write_data.size() - 14;
memcpy(fw_data, write_data.get() + 14, fw_data_size);
fbl::Vector<uint8_t> read_data = {0x0c, 0x00, 0x00, 0x00,
0x04, 0xe4, 0x05, 0x02,
0x01, 0x01, 0x00, 0x01};
sdio.ExpectFifoWrite(2, 0x18, std::move(write_data), false);
test.mock_CardRecvPacket().ExpectCall({ZX_OK, static_cast<uint32_t>(read_data.size())});
sdio.ExpectFifoRead(2, 0x1c, std::move(read_data), true);
EXPECT_NE(ZX_OK, test.CardSendFirmwarePart(vmo.get(), buffer, fw_data, fw_data_size,
BtHciMediatek::kFirmwarePartLast));
test.VerifyAll();
sdio.VerifyAndClear();
}
TEST(BtHciMediatekTest, TestCardDownloadFirmware) {
mock_sdio::MockSdio sdio;
BtHciMediatekTest test(ddk::SdioProtocolClient(sdio.GetProto()), 8);
const uint8_t fw_data[] = {0x7f, 0x26, 0x56, 0xd1, 0x44, 0x2c, 0xff, 0x5d, // Header
0xa5, 0xdf, 0x69, 0xf5, 0x0b, 0x7e, 0xc0, 0x6b,
0x50, 0xda, 0x6e, 0x0c, 0x6e, 0xb0, 0x75, 0xc3,
0xd9, 0x91, 0xff, 0x92, 0xf4, 0x06,
0x89, 0xf0, 0x13, 0x10, 0x7a, 0xa6, 0x52, 0x40, // Firmware data
0x92, 0xe5, 0x96, 0x52, 0x86, 0x14, 0x90, 0x11,
0xd1, 0x94, 0x3f, 0x2f, 0xf9, 0x6d, 0xab, 0x9e,
0xa0, 0x59, 0x0a, 0xfd};
zx::vmo vmo;
fzl::VmoMapper mapper;
ASSERT_OK(
mapper.CreateAndMap(sizeof(fw_data), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &vmo));
memcpy(mapper.start(), fw_data, sizeof(fw_data));
test.mock_CardGetHwVersion().ExpectCall({ZX_OK, 0});
test.mock_CardSendFirmwarePart().ExpectCall({ZX_OK, fw_data + 30, 8},
BtHciMediatek::kFirmwarePartFirst);
test.mock_CardSendFirmwarePart().ExpectCall({ZX_OK, fw_data + 38, 8},
BtHciMediatek::kFirmwarePartContinue);
test.mock_CardSendFirmwarePart().ExpectCall({ZX_OK, fw_data + 46, 8},
BtHciMediatek::kFirmwarePartContinue);
test.mock_CardSendFirmwarePart().ExpectCall({ZX_OK, fw_data + 54, 4},
BtHciMediatek::kFirmwarePartLast);
test.mock_CardRead32().ExpectCall({ZX_OK, 0}, 0x0c);
test.mock_CardWrite32().ExpectCall(ZX_OK, 0x0c, 2);
test.mock_CardReset().ExpectCall(ZX_OK);
EXPECT_OK(test.CardDownloadFirmware(vmo, sizeof(fw_data)));
test.VerifyAll();
sdio.VerifyAndClear();
}
TEST(BtHciMediatekTest, TestCardDownloadFirmwareEdgeCases) {
mock_sdio::MockSdio sdio;
BtHciMediatekTest test(ddk::SdioProtocolClient(sdio.GetProto()), 8);
const uint8_t fw_data[] = {0xb0, 0x4f, 0xe7, 0x35, 0x71, 0x41, 0xc4, 0xac,
0x72, 0x95, 0x63, 0x9d, 0x3c, 0x93, 0xfb, 0x0c,
0xee, 0x84, 0x05, 0xbf, 0x98, 0xe5, 0xde, 0x30,
0xf8, 0xaf, 0xbf, 0x2c, 0xfd, 0x7f,
0xc4, 0x6b, 0x59, 0x3e, 0xc2, 0xc2, 0x77, 0xc4,
0x5e, 0xe1, 0x89, 0xe4, 0x93, 0xf8, 0x0b, 0x22,
0x4b, 0x20, 0xc2, 0x9b, 0x0f, 0x6f, 0x0c, 0x4e};
zx::vmo vmo;
fzl::VmoMapper mapper;
ASSERT_OK(
mapper.CreateAndMap(sizeof(fw_data), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &vmo));
memcpy(mapper.start(), fw_data, sizeof(fw_data) - 16);
test.mock_CardGetHwVersion().ExpectCall({ZX_OK, 0});
test.mock_CardSendFirmwarePart().ExpectCall({ZX_OK, fw_data + 30, 8},
BtHciMediatek::kFirmwarePartFirst);
test.mock_CardRead32().ExpectCall({ZX_OK, 0}, 0x0c);
test.mock_CardWrite32().ExpectCall(ZX_OK, 0x0c, 2);
test.mock_CardReset().ExpectCall(ZX_OK);
EXPECT_OK(test.CardDownloadFirmware(vmo, sizeof(fw_data) - 16));
test.VerifyAll();
sdio.VerifyAndClear();
memcpy(mapper.start(), fw_data, sizeof(fw_data) - 4);
test.mock_CardGetHwVersion().ExpectCall({ZX_OK, 0});
test.mock_CardSendFirmwarePart().ExpectCall({ZX_OK, fw_data + 30, 4},
BtHciMediatek::kFirmwarePartFirst);
test.mock_CardRead32().ExpectCall({ZX_OK, 0}, 0x0c);
test.mock_CardWrite32().ExpectCall(ZX_OK, 0x0c, 2);
test.mock_CardReset().ExpectCall(ZX_OK);
EXPECT_OK(test.CardDownloadFirmware(vmo, sizeof(fw_data) - 20));
test.VerifyAll();
sdio.VerifyAndClear();
memcpy(mapper.start(), fw_data, sizeof(fw_data));
test.mock_CardGetHwVersion().ExpectCall({ZX_OK, 0});
test.mock_CardSendFirmwarePart().ExpectCall({ZX_OK, fw_data + 30, 8},
BtHciMediatek::kFirmwarePartFirst);
test.mock_CardSendFirmwarePart().ExpectCall({ZX_OK, fw_data + 38, 8},
BtHciMediatek::kFirmwarePartContinue);
test.mock_CardSendFirmwarePart().ExpectCall({ZX_OK, fw_data + 46, 8},
BtHciMediatek::kFirmwarePartLast);
test.mock_CardRead32().ExpectCall({ZX_OK, 0}, 0x0c);
test.mock_CardWrite32().ExpectCall(ZX_OK, 0x0c, 2);
test.mock_CardReset().ExpectCall(ZX_OK);
EXPECT_OK(test.CardDownloadFirmware(vmo, sizeof(fw_data)));
test.VerifyAll();
sdio.VerifyAndClear();
memcpy(mapper.start(), fw_data, sizeof(fw_data) - 24);
test.mock_CardGetHwVersion().ExpectCall({ZX_OK, 0});
test.mock_CardRead32().ExpectCall({ZX_OK, 0}, 0x0c);
test.mock_CardWrite32().ExpectCall(ZX_OK, 0x0c, 2);
test.mock_CardReset().ExpectCall(ZX_OK);
EXPECT_OK(test.CardDownloadFirmware(vmo, sizeof(fw_data) - 24));
test.VerifyAll();
sdio.VerifyAndClear();
}
TEST(BtHciMediatekTest, TestCardDownloadFirmwareFail) {
mock_sdio::MockSdio sdio;
BtHciMediatekTest test(ddk::SdioProtocolClient(sdio.GetProto()), 8);
zx::vmo vmo;
fzl::VmoMapper mapper;
ASSERT_OK(
mapper.CreateAndMap(32, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &vmo));
EXPECT_NE(ZX_OK, test.CardDownloadFirmware(vmo, 29));
test.VerifyAll();
sdio.VerifyAndClear();
test.mock_CardGetHwVersion().ExpectCall({ZX_OK, 0x8a00});
EXPECT_NE(ZX_OK, test.CardDownloadFirmware(vmo, 32));
test.VerifyAll();
sdio.VerifyAndClear();
}
} // namespace bluetooth