// 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 <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

#include <ddk/platform-defs.h>
#include <fbl/unique_ptr.h>
#include <fuchsia/hardware/hidctl/c/fidl.h>
#include <fuchsia/hardware/input/c/fidl.h>
#include <hid/boot.h>
#include <lib/driver-integration-test/fixture.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <zircon/syscalls.h>
#include <zxtest/zxtest.h>

using driver_integration_test::IsolatedDevmgr;

namespace {

class HidDriverTest : public zxtest::Test {
    void SetUp() override;

protected:
    IsolatedDevmgr devmgr_;
    fbl::unique_fd hidctl_fd_;
    zx_handle_t hidctl_fdio_channel_;
};

const board_test::DeviceEntry kDeviceEntry = []() {
    board_test::DeviceEntry entry = {};
    strcpy(entry.name, "hidctl");
    entry.vid = PDEV_VID_TEST;
    entry.pid = PDEV_PID_HIDCTL_TEST;
    return entry;
}();

void HidDriverTest::SetUp() {
    // Create the isolated dev manager
    IsolatedDevmgr::Args args;
    args.driver_search_paths.push_back("/boot/driver");
    args.device_list.push_back(kDeviceEntry);
    zx_status_t status = IsolatedDevmgr::Create(&args, &devmgr_);
    ASSERT_EQ(ZX_OK, status);

    // Wait for HidCtl to be created
    status = devmgr_integration_test::RecursiveWaitForFile(devmgr_.devfs_root(),
                                                           "sys/platform/11:04:0/hidctl",
                                                           &hidctl_fd_);
    ASSERT_EQ(ZX_OK, status);

    // Get a FIDL channel to HidCtl
    status = fdio_get_service_handle(hidctl_fd_.get(), &hidctl_fdio_channel_);
    ASSERT_EQ(ZX_OK, status);
}

const uint8_t kBootMouseReportDesc[50] = {
    0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
    0x09, 0x02, // Usage (Mouse)
    0xA1, 0x01, // Collection (Application)
    0x09, 0x01, //   Usage (Pointer)
    0xA1, 0x00, //   Collection (Physical)
    0x05, 0x09, //     Usage Page (Button)
    0x19, 0x01, //     Usage Minimum (0x01)
    0x29, 0x03, //     Usage Maximum (0x03)
    0x15, 0x00, //     Logical Minimum (0)
    0x25, 0x01, //     Logical Maximum (1)
    0x95, 0x03, //     Report Count (3)
    0x75, 0x01, //     Report Size (1)
    0x81, 0x02, //     Input (Data,Var,Abs,No Wrap,Linear,No Null Position)
    0x95, 0x01, //     Report Count (1)
    0x75, 0x05, //     Report Size (5)
    0x81, 0x03, //     Input (Const,Var,Abs,No Wrap,Linear,No Null Position)
    0x05, 0x01, //     Usage Page (Generic Desktop Ctrls)
    0x09, 0x30, //     Usage (X)
    0x09, 0x31, //     Usage (Y)
    0x15, 0x81, //     Logical Minimum (-127)
    0x25, 0x7F, //     Logical Maximum (127)
    0x75, 0x08, //     Report Size (8)
    0x95, 0x02, //     Report Count (2)
    0x81, 0x06, //     Input (Data,Var,Rel,No Wrap,Linear,No Null Position)
    0xC0,       //   End Collection
    0xC0,       // End Collection
};

TEST_F(HidDriverTest, BootMouseTest) {
    // Create a fake mouse device
    fuchsia_hardware_hidctl_HidCtlConfig config = {};
    config.dev_num = 5;
    config.boot_device = false;
    config.dev_class = 0;
    zx_handle_t hidctl_channel;
    zx_status_t status = fuchsia_hardware_hidctl_DeviceMakeHidDevice(hidctl_fdio_channel_, &config,
                                                                     kBootMouseReportDesc,
                                                                     sizeof(kBootMouseReportDesc),
                                                                     &hidctl_channel);
    ASSERT_EQ(ZX_OK, status);

    // Open the corresponding /dev/class/input/ device
    fbl::unique_fd fd_device;
    status = devmgr_integration_test::RecursiveWaitForFile(devmgr_.devfs_root(), "class/input/000",
                                                           &fd_device);
    ASSERT_EQ(ZX_OK, status);

    // Send a single mouse report
    hid_boot_mouse_report_t mouse_report = {};
    mouse_report.rel_x = 50;
    mouse_report.rel_y = 100;
    status = zx_socket_write(hidctl_channel,
                             0,
                             &mouse_report,
                             sizeof(mouse_report),
                             NULL);
    ASSERT_EQ(ZX_OK, status);

    // Check that the report comes through
    hid_boot_mouse_report_t test_report = {};
    size_t bytes_read = read(fd_device.get(), (void*)&test_report, sizeof(test_report));
    ASSERT_EQ(sizeof(test_report), bytes_read);
    ASSERT_EQ(mouse_report.rel_x, test_report.rel_x);
    ASSERT_EQ(mouse_report.rel_y, test_report.rel_y);

    // Open a FIDL channel to the HID device
    zx_handle_t device_fdio_channel;
    status = fdio_get_service_handle(fd_device.get(), &device_fdio_channel);
    ASSERT_EQ(ZX_OK, status);

    // Check that report descriptors have the same length
    uint16_t len;
    status =
        fuchsia_hardware_input_DeviceGetReportDescSize(device_fdio_channel, &len);
    ASSERT_EQ(ZX_OK, status);
    ASSERT_EQ(sizeof(kBootMouseReportDesc), len);

    // Check that report descriptors match completely
    uint8_t buf[sizeof(kBootMouseReportDesc)] = {};
    size_t actual;
    status = fuchsia_hardware_input_DeviceGetReportDesc(
        device_fdio_channel, buf, len, &actual);
    ASSERT_EQ(ZX_OK, status);
    ASSERT_EQ(sizeof(kBootMouseReportDesc), actual);
    for (size_t i = 0; i < sizeof(kBootMouseReportDesc); i++) {
        if (kBootMouseReportDesc[i] != buf[i]) {
            printf("Index %ld of the report descriptor doesn't match\n", i);
        }
        EXPECT_EQ(kBootMouseReportDesc[i], buf[i]);
    }
}

} // namespace
