// 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 #include #include #include #include #include #include "zircon_device.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; int fd = ::open(dev_name_, O_RDONLY); if (fd < 0) return static_cast(fd); ssize_t res = ::fdio_ioctl(fd, IHDA_IOCTL_GET_CHANNEL, nullptr, 0, &dev_channel_, sizeof(dev_channel_)); ::close(fd); if (res < 0) { printf("[%s] Failed to fetch device channel (%zd)\n", dev_name(), res); return static_cast(res); } return ZX_OK; } void ZirconDevice::Disconnect() { if (dev_channel_ != ZX_HANDLE_INVALID) { ::zx_handle_close(dev_channel_); dev_channel_ = ZX_HANDLE_INVALID; } } zx_status_t ZirconDevice::CallDevice(const zx_channel_call_args_t& args, uint64_t timeout_msec) { uint32_t resp_size; uint32_t resp_handles; zx_time_t deadline; if (timeout_msec == ZX_TIME_INFINITE) { deadline = ZX_TIME_INFINITE; } else if (timeout_msec >= std::numeric_limits::max() / ZX_MSEC(1)) { return ZX_ERR_INVALID_ARGS; } else { deadline = zx_deadline_after(ZX_MSEC(timeout_msec)); } return zx_channel_call(dev_channel_, 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 audio } // namespace intel_hda