blob: 341abefd75e74d953b4b1b79f79534e231160219 [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 "virtual_camera_device.h"
#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/platform-defs.h>
#include <fbl/alloc_checker.h>
#include <fbl/unique_ptr.h>
namespace virtual_camera {
zx_status_t VirtualCameraDevice::Create(void* ctx, zx_device_t* parent) {
fbl::AllocChecker ac;
auto device = fbl::make_unique_checked<VirtualCameraDevice>(&ac, parent);
if (!ac.check()) {
return ZX_ERR_NO_MEMORY;
}
zx_status_t status = device->DdkAdd("virtual_camera");
if (status != ZX_OK) {
zxlogf(
ERROR,
"virtual_camera_device: Could not create virtual camera device: %d\n",
status);
return status;
}
// device intentionally leaked as it is now held by DevMgr.
__UNUSED auto* dev = device.release();
return ZX_OK;
}
void VirtualCameraDevice::DdkUnbind() {
DdkRemove();
}
void VirtualCameraDevice::DdkRelease() {
delete this;
}
zx_status_t VirtualCameraDevice::DdkMessage(fidl_msg_t* msg, fidl_txn_t* txn) {
zx_status_t status = fuchsia_hardware_camera_Stream_try_dispatch(
this, txn, msg, &stream_ops);
if (status == ZX_ERR_NOT_SUPPORTED) {
status = fuchsia_hardware_camera_Control_try_dispatch(this, txn, msg,
&control_ops);
}
return status;
}
zx_status_t VirtualCameraDevice::StartStreaming() {
zxlogf(INFO, "virtual_camera_device: StartStreaming is not yet supported\n");
// Return ok since the function doesn't send a message back to the client.
return ZX_OK;
}
zx_status_t VirtualCameraDevice::StopStreaming() {
zxlogf(INFO, "virtual_camera_device: StopStreaming is not yet supported\n");
// Return ok since the function doesn't send a message back to the client.
return ZX_OK;
}
zx_status_t VirtualCameraDevice::ReleaseFrame(uint32_t buffer_id) {
return buffers_.BufferRelease(buffer_id);
}
zx_status_t VirtualCameraDevice::GetFormats(uint32_t index, fidl_txn_t* txn) {
fuchsia_hardware_camera_VideoFormat formats[16];
fuchsia_hardware_camera_VideoFormat format = {
.format = {.width = 640,
.height = 480,
.layers = 1,
.pixel_format =
{
.type = fuchsia_sysmem_PixelFormatType_BGRA32,
.has_format_modifier = false,
.format_modifier = {.value = 0},
},
.color_space = {.type = fuchsia_sysmem_ColorSpaceType_SRGB},
.planes = {{.byte_offset = 0, .bytes_per_row = 4 * 640},
{.byte_offset = 0, .bytes_per_row = 4 * 640},
{.byte_offset = 0, .bytes_per_row = 4 * 640},
{.byte_offset = 0, .bytes_per_row = 4 * 640}}},
.rate =
{
.frames_per_sec_numerator = 30,
.frames_per_sec_denominator = 1,
},
};
formats[0] = format;
return fuchsia_hardware_camera_ControlGetFormats_reply(txn, formats, 1, 1,
ZX_OK);
}
zx_status_t VirtualCameraDevice::CreateStream(
const fuchsia_sysmem_BufferCollectionInfo* buffer_collection_info,
const fuchsia_hardware_camera_FrameRate* rate, zx_handle_t stream,
zx_handle_t stream_token) {
return ZX_ERR_NOT_SUPPORTED;
}
zx_status_t VirtualCameraDevice::GetDeviceInfo(fidl_txn_t* txn) {
fuchsia_hardware_camera_DeviceInfo info;
info.output_capabilities = fuchsia_hardware_camera_CAMERA_OUTPUT_STREAM;
info.max_stream_count = 1;
return fuchsia_hardware_camera_ControlGetDeviceInfo_reply(txn, &info);
}
static zx_driver_ops_t driver_ops = []() {
zx_driver_ops_t ops;
ops.version = DRIVER_OPS_VERSION;
ops.bind = VirtualCameraDevice::Create;
return ops;
}();
} // namespace virtual_camera
// clang-format off
ZIRCON_DRIVER_BEGIN(virtual_camera, virtual_camera::driver_ops, "vcamera", "0.1", 3)
BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_TEST),
BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_VCAMERA_TEST),
BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_TEST_VCAMERA),
ZIRCON_DRIVER_END(virtual_camera)
// clang-format on