// Copyright 2017 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 "zircon_device.h"

#include <dirent.h>
#include <fcntl.h>
#include <fuchsia/hardware/intel/hda/c/fidl.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/io.h>
#include <stdio.h>
#include <zircon/device/intel-hda.h>

#include <limits>

#include <fbl/unique_fd.h>

namespace audio {
namespace intel_hda {

uint32_t ZirconDevice::transaction_id_ = 0;

zx_status_t ZirconDevice::Connect() {
  if (dev_channel_ != ZX_HANDLE_INVALID)
    return ZX_OK;

  if (!dev_name_)
    return ZX_ERR_NO_MEMORY;

  fbl::unique_fd fd{::open(dev_name_, O_RDONLY)};
  if (!fd.is_valid())
    return ZX_ERR_NOT_FOUND;

  fdio_cpp::FdioCaller dev(std::move(fd));
  zx_status_t (*thunk)(zx_handle_t, zx_handle_t*);

  switch (type_) {
    case Type::Controller:
      thunk = fuchsia_hardware_intel_hda_ControllerDeviceGetChannel;
      break;

    case Type::Codec:
      thunk = fuchsia_hardware_intel_hda_CodecDeviceGetChannel;
      break;

    default:
      return ZX_ERR_INTERNAL;
  }

  zx_status_t res = thunk(dev.borrow_channel(), dev_channel_.reset_and_get_address());
  if (res != ZX_OK) {
    printf("[%s] Failed to fetch device channel (%d)\n", dev_name(), res);
  }

  return res;
}

void ZirconDevice::Disconnect() { dev_channel_.reset(); }

zx_status_t ZirconDevice::CallDevice(const zx_channel_call_args_t& args, zx::duration timeout) {
  uint32_t resp_size;
  uint32_t resp_handles;
  zx::time deadline =
      timeout == zx::duration::infinite() ? zx::time::infinite() : zx::deadline_after(timeout);

  return dev_channel_.call(0, deadline, &args, &resp_size, &resp_handles);
}

zx_status_t ZirconDevice::Enumerate(void* ctx, const char* const dev_path, EnumerateCbk cbk) {
  static constexpr size_t FILENAME_SIZE = 256;

  struct dirent* de;
  DIR* dir = opendir(dev_path);
  zx_status_t res = ZX_OK;
  char buf[FILENAME_SIZE];

  if (!dir)
    return ZX_ERR_NOT_FOUND;

  while ((de = readdir(dir)) != NULL) {
    uint32_t id;
    if (sscanf(de->d_name, "%u", &id) == 1) {
      size_t total = 0;

      total += snprintf(buf + total, sizeof(buf) - total, "%s/", dev_path);
      total += snprintf(buf + total, sizeof(buf) - total, "%03u", id);

      res = cbk(ctx, id, buf);
      if (res != ZX_OK)
        goto done;
    }
  }

done:
  closedir(dir);
  return res;
}

}  // namespace intel_hda
}  // namespace audio
