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 #include <memory>
6 
7 #include <assert.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 
12 #include <ddk/binding.h>
13 #include <ddk/debug.h>
14 #include <ddk/device.h>
15 #include <ddk/driver.h>
16 #include <ddk/platform-defs.h>
17 #include <ddk/protocol/platform/bus.h>
18 
19 #include <zircon/process.h>
20 #include <zircon/syscalls.h>
21 #include <zircon/assert.h>
22 
23 #include "test.h"
24 #include "test-resources.h"
25 
26 namespace board_test {
27 
DdkRelease()28 void TestBoard::DdkRelease() {
29     delete this;
30 }
31 
Thread()32 int TestBoard::Thread() {
33     zx_status_t status;
34 
35     status = GpioInit();
36     if (status != ZX_OK) {
37         zxlogf(ERROR, "%s: GpioInit failed: %d\n", __func__, status);
38     }
39 
40     status = TestInit();
41     if (status != ZX_OK) {
42         zxlogf(ERROR, "%s: TestInit failed: %d\n", __func__, status);
43     }
44     return 0;
45 }
46 
Start()47 zx_status_t TestBoard::Start() {
48     int rc = thrd_create_with_name(&thread_,
49                                    [](void* arg) -> int {
50                                        return reinterpret_cast<TestBoard*>(arg)->Thread();
51                                    },
52                                    this,
53                                    "test-board-start-thread");
54     if (rc != thrd_success) {
55         return ZX_ERR_INTERNAL;
56     }
57     return ZX_OK;
58 }
59 
Create(zx_device_t * parent)60 zx_status_t TestBoard::Create(zx_device_t* parent) {
61     pbus_protocol_t pbus;
62     if (device_get_protocol(parent, ZX_PROTOCOL_PBUS, &pbus) != ZX_OK) {
63         return ZX_ERR_NOT_SUPPORTED;
64     }
65 
66     auto board = std::make_unique<TestBoard>(parent, &pbus);
67 
68     zx_status_t status = board->DdkAdd("test-board", DEVICE_ADD_NON_BINDABLE);
69     if (status != ZX_OK) {
70         zxlogf(ERROR, "TestBoard::Create: DdkAdd failed: %d\n", status);
71         return status;
72     }
73 
74     status = board->Start();
75     if (status == ZX_OK) {
76       // devmgr is now in charge of the device.
77       __UNUSED auto* dummy = board.release();
78     }
79 
80     return status;
81 }
82 
test_bind(void * ctx,zx_device_t * parent)83 zx_status_t test_bind(void* ctx, zx_device_t* parent) {
84     return TestBoard::Create(parent);
85 }
86 
__anone9525d590202()87 static zx_driver_ops_t driver_ops = [](){
88     zx_driver_ops_t ops;
89     ops.version = DRIVER_OPS_VERSION;
90     ops.bind = test_bind;
91     return ops;
92 }();
93 
94 } // namespace board_test
95 
96 ZIRCON_DRIVER_BEGIN(test_bus, board_test::driver_ops, "zircon", "0.1", 3)
97     BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PBUS),
98     BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_TEST),
99     BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_PID, PDEV_PID_PBUS_TEST),
100 ZIRCON_DRIVER_END(test_bus)
101