1 // Copyright 2018 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
6 #include <stdlib.h>
7
8 #include <utility>
9
10 #include <lib/fake_ddk/fake_ddk.h>
11 #include <unittest/unittest.h>
12 #include <zircon/assert.h>
13
14 namespace fake_ddk {
15
16 zx_device_t* kFakeDevice = reinterpret_cast<zx_device_t*>(0x55);
17 zx_device_t* kFakeParent = reinterpret_cast<zx_device_t*>(0xaa);
18
19 Bind* Bind::instance_ = nullptr;
20
Bind()21 Bind::Bind() {
22 ZX_ASSERT(!instance_);
23 instance_ = this;
24 }
25
Ok()26 bool Bind::Ok() {
27 BEGIN_HELPER;
28 EXPECT_TRUE(add_called_);
29 EXPECT_TRUE(remove_called_);
30 EXPECT_FALSE(bad_parent_);
31 EXPECT_FALSE(bad_device_);
32 END_HELPER;
33 }
34
ExpectMetadata(const void * data,size_t data_length)35 void Bind::ExpectMetadata(const void* data, size_t data_length) {
36 metadata_ = data;
37 metadata_length_ = data_length;
38 }
39
GetMetadataInfo(int * num_calls,size_t * length)40 void Bind::GetMetadataInfo(int* num_calls, size_t* length) {
41 *num_calls = add_metadata_calls_;
42 *length = metadata_length_;
43 }
44
SetProtocols(fbl::Array<ProtocolEntry> && protocols)45 void Bind::SetProtocols(fbl::Array<ProtocolEntry>&& protocols) {
46 protocols_ = std::move(protocols);
47 }
48
DeviceAdd(zx_driver_t * drv,zx_device_t * parent,device_add_args_t * args,zx_device_t ** out)49 zx_status_t Bind::DeviceAdd(zx_driver_t* drv, zx_device_t* parent,
50 device_add_args_t* args, zx_device_t** out) {
51 if (parent != kFakeParent) {
52 bad_parent_ = true;
53 }
54
55 *out = kFakeDevice;
56 add_called_ = true;
57 return ZX_OK;
58 }
59
DeviceRemove(zx_device_t * device)60 zx_status_t Bind::DeviceRemove(zx_device_t* device) {
61 if (device != kFakeDevice) {
62 bad_device_ = true;
63 }
64 remove_called_ = true;
65 return ZX_OK;
66 }
67
DeviceAddMetadata(zx_device_t * device,uint32_t type,const void * data,size_t length)68 zx_status_t Bind::DeviceAddMetadata(zx_device_t* device, uint32_t type, const void* data,
69 size_t length) {
70 if (device != kFakeDevice) {
71 bad_device_ = true;
72 }
73
74 if (metadata_) {
75 if (length != metadata_length_ || memcmp(data, metadata_, length) != 0) {
76 unittest_printf_critical("Unexpected metadata\n");
77 return ZX_ERR_BAD_STATE;
78 }
79 } else {
80 metadata_length_ += length;
81 }
82 add_metadata_calls_++;
83 return ZX_OK;
84 }
85
DeviceMakeVisible(zx_device_t * device)86 void Bind::DeviceMakeVisible(zx_device_t* device) {
87 if (device != kFakeDevice) {
88 bad_device_ = true;
89 }
90 make_visible_called_ = true;
91 return;
92 }
93
DeviceGetProtocol(const zx_device_t * device,uint32_t proto_id,void * protocol)94 zx_status_t Bind::DeviceGetProtocol(const zx_device_t* device, uint32_t proto_id, void* protocol) {
95 if (device != kFakeParent) {
96 bad_device_ = true;
97 return ZX_ERR_NOT_SUPPORTED;
98 }
99 auto out = reinterpret_cast<Protocol*>(protocol);
100 for (const auto& proto : protocols_) {
101 if (proto_id == proto.id) {
102 out->ops = proto.proto.ops;
103 out->ctx = proto.proto.ctx;
104 return ZX_OK;
105 }
106 }
107 return ZX_ERR_NOT_SUPPORTED;
108 }
109
DeviceGetName(zx_device_t * device)110 const char* Bind::DeviceGetName(zx_device_t* device) {
111 if (device != kFakeParent) {
112 bad_device_ = true;
113 }
114 return "";
115 }
116
117 } // namespace fake_ddk
118
device_add_from_driver(zx_driver_t * drv,zx_device_t * parent,device_add_args_t * args,zx_device_t ** out)119 zx_status_t device_add_from_driver(zx_driver_t* drv, zx_device_t* parent,
120 device_add_args_t* args, zx_device_t** out) {
121 if (!fake_ddk::Bind::Instance()) {
122 return ZX_OK;
123 }
124 return fake_ddk::Bind::Instance()->DeviceAdd(drv, parent, args, out);
125 }
126
device_remove(zx_device_t * device)127 zx_status_t device_remove(zx_device_t* device) {
128 if (!fake_ddk::Bind::Instance()) {
129 return ZX_OK;
130 }
131 return fake_ddk::Bind::Instance()->DeviceRemove(device);
132 }
133
device_add_metadata(zx_device_t * device,uint32_t type,const void * data,size_t length)134 zx_status_t device_add_metadata(zx_device_t* device, uint32_t type, const void* data,
135 size_t length) {
136 if (!fake_ddk::Bind::Instance()) {
137 return ZX_OK;
138 }
139 return fake_ddk::Bind::Instance()->DeviceAddMetadata(device, type, data, length);
140 }
141
device_make_visible(zx_device_t * device)142 void device_make_visible(zx_device_t* device) {
143 if (fake_ddk::Bind::Instance()) {
144 fake_ddk::Bind::Instance()->DeviceMakeVisible(device);
145 }
146 return;
147 }
148
device_get_protocol(const zx_device_t * device,uint32_t proto_id,void * protocol)149 zx_status_t device_get_protocol(const zx_device_t* device, uint32_t proto_id, void* protocol) {
150 if (!fake_ddk::Bind::Instance()) {
151 return ZX_ERR_NOT_SUPPORTED;
152 }
153 return fake_ddk::Bind::Instance()->DeviceGetProtocol(device, proto_id, protocol);
154 }
155
device_get_name(zx_device_t * device)156 const char* device_get_name(zx_device_t* device) {
157 if (!fake_ddk::Bind::Instance()) {
158 return nullptr;
159 }
160 return fake_ddk::Bind::Instance()->DeviceGetName(device);
161 }
162
driver_printf(uint32_t flags,const char * fmt,...)163 extern "C" void driver_printf(uint32_t flags, const char* fmt, ...) {}
164
165 zx_driver_rec __zircon_driver_rec__ = {};
166