blob: df80281bc4cf662dbcd778e25bb266b09924b022 [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 <ddk/platform-defs.h>
#include <fuchsia/camera/common/c/fidl.h>
#include <fuchsia/camera/common/llcpp/fidl.h>
#include <fuchsia/hardware/camera/c/fidl.h>
#include <lib/driver-integration-test/fixture.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/zx/eventpair.h>
#include <lib/zx/vmo.h>
#include <zxtest/zxtest.h>
#include <zircon/syscalls.h>
using driver_integration_test::IsolatedDevmgr;
namespace {
constexpr uint32_t kPageSize = 4096;
// TODO(CAM-43): Replace with sysmem version when available?
zx_status_t Gralloc(fuchsia_camera_common_VideoFormat format, uint32_t num_buffers,
fuchsia_sysmem_BufferCollectionInfo* buffer_collection,
zx::vmo vmos[64]) {
// In the future, some special alignment might happen here, or special
// memory allocated...
// Simple GetBufferSize. Only valid for simple formats:
size_t buffer_size = fbl::round_up(
format.format.height * format.format.planes[0].bytes_per_row, kPageSize);
buffer_collection->buffer_count = num_buffers;
buffer_collection->vmo_size = buffer_size;
buffer_collection->format.image = format.format;
zx_status_t status;
for (uint32_t i = 0; i < num_buffers; ++i) {
status = zx::vmo::create(buffer_size, 0, &vmos[i]);
if (status != ZX_OK) {
return status;
}
buffer_collection->vmos[i] = vmos[i].get();
}
return ZX_OK;
}
// Integration test for the driver defined in zircon/system/dev/virtual_camera.
// This test code loads the driver into an isolated devmgr and tests behavior.
class VirtualCameraTest : public zxtest::Test {
void SetUp() override;
protected:
IsolatedDevmgr devmgr_;
fbl::unique_fd fd_;
zx_handle_t device_handle_;
fuchsia_sysmem_BufferCollectionInfo info_0_;
zx::vmo vmos_0_[64];
};
const board_test::DeviceEntry kDeviceEntry = []() {
board_test::DeviceEntry entry = {};
entry.vid = PDEV_VID_TEST;
entry.pid = PDEV_PID_VCAMERA_TEST;
entry.did = PDEV_DID_TEST_VCAMERA;
return entry;
}();
void VirtualCameraTest::SetUp() {
IsolatedDevmgr::Args args;
args.driver_search_paths.push_back("/boot/driver");
args.driver_search_paths.push_back("/boot/driver/test");
args.device_list.push_back(kDeviceEntry);
zx_status_t status = IsolatedDevmgr::Create(&args, &devmgr_);
ASSERT_EQ(status, ZX_OK);
status = devmgr_integration_test::RecursiveWaitForFile(
devmgr_.devfs_root(), "sys/platform/11:05:b/virtual_camera",
zx::time::infinite(), &fd_);
ASSERT_EQ(ZX_OK, status);
status = fdio_get_service_handle(fd_.get(), &device_handle_);
ASSERT_EQ(ZX_OK, status);
}
TEST_F(VirtualCameraTest, GetDeviceInfoGetFormatsTest) {
fuchsia_hardware_camera_DeviceInfo device_info;
zx_status_t status =
fuchsia_hardware_camera_ControlV2GetDeviceInfo(device_handle_, &device_info);
ASSERT_EQ(ZX_OK, status);
EXPECT_EQ(1, device_info.max_stream_count);
EXPECT_EQ(fuchsia_hardware_camera_CAMERA_OUTPUT_STREAM,
device_info.output_capabilities);
fuchsia_camera_common_VideoFormat formats[16];
uint32_t total_count;
uint32_t actual_count;
int32_t out_status;
status = fuchsia_hardware_camera_ControlV2GetFormats(
device_handle_, 1, formats, &total_count, &actual_count, &out_status);
ASSERT_EQ(ZX_OK, status);
auto format = formats[0];
EXPECT_EQ(640, format.format.width);
EXPECT_EQ(480, format.format.height);
EXPECT_EQ(1, format.format.layers);
EXPECT_EQ(30, format.rate.frames_per_sec_numerator);
EXPECT_EQ(1, format.rate.frames_per_sec_denominator);
EXPECT_EQ(1, total_count);
EXPECT_EQ(1, actual_count);
zx::eventpair driver_token;
zx::eventpair stream_token;
status = zx::eventpair::create(0, &stream_token, &driver_token);
ASSERT_EQ(ZX_OK, status);
zx::channel client_request;
zx::channel server_request;
status = zx::channel::create(0, &client_request, &server_request);
ASSERT_EQ(ZX_OK, status);
status = Gralloc(format, 2, &info_0_, vmos_0_);
ASSERT_EQ(ZX_OK, status);
status = fuchsia_hardware_camera_ControlV2CreateStream(
device_handle_, &info_0_, &format.rate, server_request.release(), driver_token.release());
ASSERT_EQ(ZX_OK, status);
// Not fully implemented yet - this is a sanity check.
zx_handle_t stream_handle = client_request.release();
status = fuchsia_camera_common_StreamStart(stream_handle);
EXPECT_EQ(ZX_OK, status);
stream_token.reset();
zx_signals_t pending;
zx::time deadline = zx::deadline_after(zx::sec(5));
zx::channel client = zx::channel(stream_handle);
ASSERT_EQ(ZX_OK, client.wait_one(ZX_CHANNEL_PEER_CLOSED, deadline, &pending));
ASSERT_EQ(pending & ZX_CHANNEL_PEER_CLOSED, ZX_CHANNEL_PEER_CLOSED);
}
} // namespace