blob: 05efa64776c7d232e5ddb4ec20f117138fc2d986 [file] [log] [blame]
// 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 "test-driver-child.h"
#include <ddk/debug.h>
#include <ddktl/device.h>
#include <fbl/alloc_checker.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
void TestLifecycleDriverChild::DdkRelease() {
// Release the reference now that devmgr no longer has a pointer to this object.
__UNUSED bool dummy = Release();
}
void TestLifecycleDriverChild::AsyncRemove(fit::function<void()> callback) {
async_remove_ = true;
unbind_callback_ = std::move(callback);
DdkAsyncRemove();
}
void TestLifecycleDriverChild::CompleteUnbind() { unbind_txn_->Reply(); }
zx_status_t TestLifecycleDriverChild::Create(zx_device_t* parent, bool complete_init,
zx_status_t init_status,
fbl::RefPtr<TestLifecycleDriverChild>* out_device) {
fbl::AllocChecker ac;
auto device =
fbl::MakeRefCountedChecked<TestLifecycleDriverChild>(&ac, parent, complete_init, init_status);
if (!ac.check()) {
return ZX_ERR_NO_MEMORY;
}
*out_device = device;
zx_status_t status = device->DdkAdd("ddk-lifecycle-test-child");
if (status != ZX_OK) {
out_device->reset();
return status;
}
// Hold a reference while devmgr has a pointer to this object.
device->AddRef();
return ZX_OK;
}
zx_status_t TestLifecycleDriverChild::DdkOpen(zx_device_t** dev_out, uint32_t flags) {
return (new InstanceDevice(zxdev()))->Add(dev_out);
}
void TestLifecycleDriverChild::DdkInit(ddk::InitTxn txn) {
if (complete_init_) {
txn.Reply(init_status_);
replied_to_init_ = true;
} else {
init_txn_ = std::move(txn);
}
}
void TestLifecycleDriverChild::DdkUnbind(ddk::UnbindTxn txn) {
ZX_ASSERT(!init_txn_);
if (async_remove_) {
unbind_txn_ = std::move(txn);
(*unbind_callback_)();
return;
}
txn.Reply();
}
zx_status_t TestLifecycleDriverChild::CompleteInit() {
if (replied_to_init_) {
zxlogf(ERROR, "Already replied to init");
return ZX_ERR_BAD_STATE;
}
if (!init_txn_) {
// The init hook has not been called yet.
complete_init_ = true;
return ZX_OK;
}
init_txn_->Reply(init_status_);
init_txn_ = std::nullopt;
replied_to_init_ = true;
return ZX_OK;
}