blob: 9faaa4ae7c7d1ec31833ea3aa47648b5fd65414d [file] [log] [blame]
// 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 <cstdio>
#include <future>
#include <thread>
#include <lib/zx/channel.h>
#include <lib/async/cpp/task.h>
#include <zircon/device/qmi-transport.h>
#include <zircon/status.h>
#include <zircon/types.h>
#include "fake-device.h"
namespace qmi_fake {
Device::Device(zx_device_t* device) : parent_(device) {}
#define DEV(c) static_cast<Device*>(c)
static zx_protocol_device_t qmi_fake_device_ops = {
.version = DEVICE_OPS_VERSION,
.unbind = [](void* ctx) { DEV(ctx)->Unbind(); },
.get_protocol = [](void* ctx, uint32_t proto_id, void* out_proto)
-> zx_status_t { return DEV(ctx)->GetProtocol(proto_id, out_proto); },
.release = [](void* ctx) { DEV(ctx)->Release(); },
.ioctl = [](void* ctx, uint32_t op, const void* in_buf, size_t in_len,
void* out_buf, size_t out_len,
size_t* out_actual) -> zx_status_t {
return DEV(ctx)->Ioctl(op, in_buf, in_len, out_buf, out_len, out_actual);
},
};
#undef DEV
zx_status_t Device::Bind() {
device_add_args_t args = {};
args.version = DEVICE_ADD_ARGS_VERSION;
args.name = "qmi-fake";
args.ctx = this;
args.ops = &qmi_fake_device_ops;
args.proto_id = ZX_PROTOCOL_QMI_TRANSPORT;
zx_status_t status = device_add(parent_, &args, &zxdev_);
if (status != ZX_OK) {
printf("qmi-fake: could not add device: %d\n", status);
return status;
}
return status;
}
void Device::Release() { delete this; }
void Device::Unbind() {
device_remove(zxdev_);
}
zx_status_t Device::Ioctl(uint32_t op, const void* in_buf, size_t in_len,
void* out_buf, size_t out_len, size_t* out_actual) {
printf("%s\n", __func__);
zx_handle_t* reply = static_cast<zx_handle_t*>(out_buf);
zx_status_t status = ZX_ERR_NOT_SUPPORTED;
if (op == IOCTL_QMI_GET_CHANNEL) {
status = OpenChan(reply);
}
if (status == ZX_OK) {
*out_actual = sizeof(*reply);
}
return status;
}
zx_status_t Device::GetProtocol(uint32_t proto_id, void* out_proto) {
printf("%s\n", __func__);
if (proto_id != ZX_PROTOCOL_QMI_TRANSPORT) {
return ZX_ERR_NOT_SUPPORTED;
}
return ZX_OK;
}
zx_status_t Device::OpenChan(zx_handle_t* out_channel) {
zx::channel in, out;
auto status = zx::channel::create(0, &out, &in);
if (status != ZX_OK) {
printf("qmi-fake: could not create channel: %d\n", status);
return status;
}
*out_channel = out.release();
hold_chan_ = in.release();
return ZX_OK;
}
} // namespace qmi_fake