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 <stdlib.h>
6 
7 #include <ddk/binding.h>
8 #include <ddk/debug.h>
9 #include <ddk/device.h>
10 #include <ddk/driver.h>
11 #include <ddk/platform-defs.h>
12 #include <ddk/protocol/gpio.h>
13 #include <ddk/protocol/platform/device.h>
14 
15 #define DRIVER_NAME "test-child-2"
16 
17 typedef struct {
18     zx_device_t* zxdev;
19 } test_t;
20 
test_release(void * ctx)21 static void test_release(void* ctx) {
22     free(ctx);
23 }
24 
25 static zx_protocol_device_t test_device_protocol = {
26     .version = DEVICE_OPS_VERSION,
27     .release = test_release,
28 };
29 
test_gpio(pdev_protocol_t * pdev)30 static zx_status_t test_gpio(pdev_protocol_t* pdev) {
31     zx_status_t status;
32     gpio_protocol_t gpio;
33     size_t actual;
34 
35     status = pdev_get_protocol(pdev, ZX_PROTOCOL_GPIO, 0, &gpio, sizeof(gpio), &actual);
36     if (status != ZX_OK) {
37         zxlogf(ERROR, "%s: failed to get gpio, st = %d\n", DRIVER_NAME, status);
38     }
39 
40     return status;
41 }
42 
test_bind(void * ctx,zx_device_t * parent)43 static zx_status_t test_bind(void* ctx, zx_device_t* parent) {
44     pdev_protocol_t pdev;
45     zx_status_t status;
46 
47     zxlogf(INFO, "test_bind: %s \n", DRIVER_NAME);
48 
49     status = device_get_protocol(parent, ZX_PROTOCOL_PDEV, &pdev);
50     if (status != ZX_OK) {
51         zxlogf(ERROR, "%s: could not get ZX_PROTOCOL_PDEV\n", DRIVER_NAME);
52         return status;
53     }
54 
55     status = test_gpio(&pdev);
56     if (status != ZX_OK) {
57         zxlogf(ERROR, "%s: gpio test failed, st = %d\n", DRIVER_NAME, status);
58     }
59 
60     test_t* test = calloc(1, sizeof(test_t));
61     if (!test) {
62         return ZX_ERR_NO_MEMORY;
63     }
64 
65     device_add_args_t args = {
66         .version = DEVICE_ADD_ARGS_VERSION,
67         .name = "child-2",
68         .ctx = test,
69         .ops = &test_device_protocol,
70         .flags = DEVICE_ADD_NON_BINDABLE,
71     };
72 
73     status = device_add(parent, &args, &test->zxdev);
74     if (status != ZX_OK) {
75         zxlogf(ERROR, "%s: device_add failed: %d\n", DRIVER_NAME, status);
76         free(test);
77         return status;
78     }
79 
80     return ZX_OK;
81 }
82 
83 static zx_driver_ops_t test_driver_ops = {
84     .version = DRIVER_OPS_VERSION,
85     .bind = test_bind,
86 };
87 
88 ZIRCON_DRIVER_BEGIN(test_bus, test_driver_ops, "zircon", "0.1", 4)
89     BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PDEV),
90     BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_TEST),
91     BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_PBUS_TEST),
92     BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_TEST_CHILD_2),
93 ZIRCON_DRIVER_END(test_bus)
94