| // Copyright 2018 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/camera/test/camera_client_test/camera_client_test.h" |
| |
| #include <fbl/unique_fd.h> |
| #include <fcntl.h> |
| #include <fuchsia/hardware/camera/c/fidl.h> |
| #include <lib/fzl/fdio.h> |
| #include <src/lib/fxl/logging.h> |
| #include <src/lib/fxl/strings/string_printf.h> |
| |
| #include <iostream> |
| |
| namespace camera { |
| |
| Client::Client() : Client(sys::ComponentContext::Create()) {} |
| |
| Client::Client(std::unique_ptr<sys::ComponentContext> context) |
| : context_(std::move(context)) {} |
| |
| fuchsia::camera::ControlSyncPtr &Client::camera() { return camera_control_; } |
| |
| fuchsia::camera::ManagerSyncPtr &Client::manager() { return manager_; } |
| |
| zx_status_t Client::LoadVideoFormats( |
| fit::function<zx_status_t( |
| uint32_t index, std::vector<fuchsia::camera::VideoFormat> *formats, |
| uint32_t *total_format_count)> |
| get_formats) { |
| uint32_t total_format_count; |
| uint32_t format_index = 0; |
| do { |
| std::vector<fuchsia::camera::VideoFormat> call_formats; |
| |
| zx_status_t status = |
| get_formats(format_index, &call_formats, &total_format_count); |
| if (status != ZX_OK) { |
| FXL_LOG(ERROR) << "Couldn't get camera formats (status " << status << ")"; |
| return status; |
| } |
| |
| for (auto &&f : call_formats) { |
| formats_.push_back(f); |
| } |
| format_index += call_formats.size(); |
| } while (formats_.size() < total_format_count); |
| |
| printf("Available formats: %zd\n", formats_.size()); |
| for (size_t i = 0; i < formats_.size(); i++) { |
| printf("format[%zd] - width: %d, height: %d, stride: %u\n", i, |
| formats_[i].format.width, formats_[i].format.height, |
| static_cast<uint32_t>(formats_[i].format.planes[0].bytes_per_row)); |
| } |
| |
| return ZX_OK; |
| } |
| |
| static void dump_device_info(const fuchsia::camera::DeviceInfo &device_info) { |
| std::cout << "Device Info - camera_id: " << device_info.camera_id |
| << ", vendor_id: " << device_info.vendor_id |
| << ", vendor_name: " << device_info.vendor_name << "\n" |
| << " product_id: " << device_info.product_id |
| << ", product_name: " << device_info.product_name |
| << ", serial_number: " << device_info.serial_number << "\n" |
| << " max_stream_count: " << device_info.max_stream_count |
| << ", output_capabilities: " << device_info.output_capabilities |
| << "\n"; |
| } |
| |
| zx_status_t Client::StartManager(int device_id) { |
| // Connect to Camera Manager: |
| context_->svc()->Connect(manager().NewRequest()); |
| |
| std::vector<fuchsia::camera::DeviceInfo> devices; |
| zx_status_t status = manager()->GetDevices(&devices); |
| if (status != ZX_OK) { |
| FXL_LOG(ERROR) << "Failed to get devices. error: " << status; |
| return status; |
| } |
| |
| std::cout << "Obtained " << devices.size() << " devices\n"; |
| for (const auto &device : devices) { |
| dump_device_info(device); |
| } |
| |
| return LoadVideoFormats( |
| [device_id, &devices, this]( |
| uint32_t format_index, |
| std::vector<fuchsia::camera::VideoFormat> *formats, |
| uint32_t *total_format_count) { |
| return manager()->GetFormats(devices[device_id].camera_id, format_index, |
| formats, total_format_count); |
| }); |
| } |
| |
| zx_status_t Client::StartDriver(const char *device) { |
| zx_status_t status = Open(device); |
| if (status != ZX_OK) { |
| FXL_LOG(ERROR) << "Couldn't open camera client (status " << status << ")"; |
| return status; |
| } |
| |
| fuchsia::camera::DeviceInfo device_info; |
| status = camera()->GetDeviceInfo(&device_info); |
| |
| if (status != ZX_OK) { |
| FXL_LOG(ERROR) << "Couldn't get device info (status " << status << ")"; |
| return status; |
| } |
| |
| dump_device_info(device_info); |
| |
| return LoadVideoFormats( |
| [this](uint32_t format_index, |
| std::vector<fuchsia::camera::VideoFormat> *formats, |
| uint32_t *total_format_count) { |
| zx_status_t driver_status; |
| zx_status_t status = camera()->GetFormats( |
| format_index, formats, total_format_count, &driver_status); |
| return driver_status == ZX_OK ? status : driver_status; |
| }); |
| } |
| |
| zx_status_t Client::Open(const char *device) { |
| std::string dev_path = device; |
| fbl::unique_fd dev_node{::open(dev_path.c_str(), O_RDONLY)}; |
| if (!dev_node.is_valid()) { |
| FXL_LOG(ERROR) << "Client::Open failed to open device node at \"" |
| << dev_path << "\". (" << strerror(errno) << " : " << errno |
| << ")"; |
| return ZX_ERR_IO; |
| } |
| zx::channel local, remote; |
| zx_status_t status = zx::channel::create(0u, &local, &remote); |
| FXL_CHECK(status == ZX_OK) << "Failed to create channel. status " << status; |
| |
| fzl::FdioCaller dev(std::move(dev_node)); |
| zx_status_t res = fuchsia_hardware_camera_DeviceGetChannel( |
| dev.borrow_channel(), remote.release()); |
| if (res != ZX_OK) { |
| FXL_LOG(ERROR) << "Failed to obtain channel (res " << res << ")"; |
| return res; |
| } |
| |
| camera().Bind(std::move(local)); |
| |
| return ZX_OK; |
| } |
| |
| } // namespace camera |