1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <dirent.h> 6#include <fcntl.h> 7#include <stdio.h> 8 9#include <zircon/device/intel-hda.h> 10#include <lib/fdio/io.h> 11#include <fbl/limits.h> 12 13#include "zircon_device.h" 14 15namespace audio { 16namespace intel_hda { 17 18uint32_t ZirconDevice::transaction_id_ = 0; 19 20zx_status_t ZirconDevice::Connect() { 21 if (dev_channel_ != ZX_HANDLE_INVALID) 22 return ZX_OK; 23 24 if (!dev_name_) 25 return ZX_ERR_NO_MEMORY; 26 27 int fd = ::open(dev_name_, O_RDONLY); 28 if (fd < 0) 29 return static_cast<zx_status_t>(fd); 30 31 ssize_t res = ::fdio_ioctl(fd, IHDA_IOCTL_GET_CHANNEL, 32 nullptr, 0, 33 &dev_channel_, sizeof(dev_channel_)); 34 ::close(fd); 35 36 if (res < 0) { 37 printf("[%s] Failed to fetch device channel (%zd)\n", dev_name(), res); 38 return static_cast<zx_status_t>(res); 39 } 40 41 return ZX_OK; 42} 43 44void ZirconDevice::Disconnect() { 45 if (dev_channel_ != ZX_HANDLE_INVALID) { 46 ::zx_handle_close(dev_channel_); 47 dev_channel_ = ZX_HANDLE_INVALID; 48 } 49} 50 51zx_status_t ZirconDevice::CallDevice(const zx_channel_call_args_t& args, uint64_t timeout_msec) { 52 uint32_t resp_size; 53 uint32_t resp_handles; 54 zx_time_t deadline; 55 56 if (timeout_msec == ZX_TIME_INFINITE) { 57 deadline = ZX_TIME_INFINITE; 58 } else if (timeout_msec >= fbl::numeric_limits<zx_time_t>::max() / ZX_MSEC(1)) { 59 return ZX_ERR_INVALID_ARGS; 60 } else { 61 deadline = zx_deadline_after(ZX_MSEC(timeout_msec)); 62 } 63 64 return zx_channel_call(dev_channel_, 0, deadline, &args, &resp_size, &resp_handles); 65} 66 67zx_status_t ZirconDevice::Enumerate( 68 void* ctx, 69 const char* const dev_path, 70 EnumerateCbk cbk) { 71 static constexpr size_t FILENAME_SIZE = 256; 72 73 struct dirent* de; 74 DIR* dir = opendir(dev_path); 75 zx_status_t res = ZX_OK; 76 char buf[FILENAME_SIZE]; 77 78 if (!dir) 79 return ZX_ERR_NOT_FOUND; 80 81 while ((de = readdir(dir)) != NULL) { 82 uint32_t id; 83 if (sscanf(de->d_name, "%u", &id) == 1) { 84 size_t total = 0; 85 86 total += snprintf(buf + total, sizeof(buf) - total, "%s/", dev_path); 87 total += snprintf(buf + total, sizeof(buf) - total, "%03u", id); 88 89 res = cbk(ctx, id, buf); 90 if (res != ZX_OK) 91 goto done; 92 } 93 } 94 95done: 96 closedir(dir); 97 return res; 98} 99 100} // namespace audio 101} // namespace intel_hda 102