[astro][hid-buttons] Convert to use composite protocol

Based on a CL by voydanoff@.

Test: Device enumeration and hid-buttons unit tests, and trace button
presses on astro, sherlock and cleo.

Change-Id: I8bca5e988b0aa4f921de4b540a03b267687a4f9d
diff --git a/zircon/system/dev/board/astro/astro-buttons.c b/zircon/system/dev/board/astro/astro-buttons.c
index 2424e0e..5f03134 100644
--- a/zircon/system/dev/board/astro/astro-buttons.c
+++ b/zircon/system/dev/board/astro/astro-buttons.c
@@ -2,37 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <ddk/binding.h>
 #include <ddk/debug.h>
 #include <ddk/device.h>
 #include <ddk/metadata.h>
 #include <ddk/metadata/buttons.h>
 #include <ddk/platform-defs.h>
-#include <ddk/protocol/platform/bus.h>
 
 #include <soc/aml-s905d2/s905d2-gpio.h>
 #include <soc/aml-s905d2/s905d2-hw.h>
 
 #include "astro.h"
-
-static const pbus_gpio_t astro_buttons_gpios[] = {
-    {
-        // Volume up.
-        .gpio = S905D2_GPIOZ(5),
-    },
-    {
-        // Volume down.
-        .gpio = S905D2_GPIOZ(6),
-    },
-    {
-        // Both Volume up and down pressed.
-        .gpio = S905D2_GPIOAO(10),
-    },
-    {
-        // Mic privacy switch.
-        .gpio = S905D2_GPIOZ(2),
-
-    },
-};
+#include "astro-gpios.h"
 
 // clang-format off
 static const buttons_button_config_t buttons[] = {
@@ -63,22 +44,61 @@
     }
 };
 
-static pbus_dev_t astro_buttons_dev = {
-    .name = "astro-buttons",
-    .vid = PDEV_VID_GENERIC,
-    .pid = PDEV_PID_GENERIC,
-    .did = PDEV_DID_HID_BUTTONS,
-    .gpio_list = astro_buttons_gpios,
-    .gpio_count = countof(astro_buttons_gpios),
-    .metadata_list = available_buttons_metadata,
-    .metadata_count = countof(available_buttons_metadata),
+static const zx_bind_inst_t root_match[] = {
+    BI_MATCH(),
+};
+static const zx_bind_inst_t volume_up_match[] = {
+    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+    BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_VOLUME_UP),
+};
+static const zx_bind_inst_t volume_down_match[] = {
+    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+    BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_VOLUME_DOWN),
+};
+static const zx_bind_inst_t volume_both_match[] = {
+    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+    BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_VOLUME_BOTH),
+};
+static const zx_bind_inst_t mic_privacy_match[] = {
+    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+    BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_MIC_PRIVACY),
+};
+static const device_component_part_t volume_up_component[] = {
+    { countof(root_match), root_match },
+    { countof(volume_up_match), volume_up_match },
+};
+static const device_component_part_t volume_down_component[] = {
+    { countof(root_match), root_match },
+    { countof(volume_down_match), volume_down_match },
+};
+static const device_component_part_t volume_both_component[] = {
+    { countof(root_match), root_match },
+    { countof(volume_both_match), volume_both_match },
+};
+static const device_component_part_t mic_privacy_component[] = {
+    { countof(root_match), root_match },
+    { countof(mic_privacy_match), mic_privacy_match },
+};
+static const device_component_t components[] = {
+    { countof(volume_up_component), volume_up_component },
+    { countof(volume_down_component), volume_down_component },
+    { countof(volume_both_component), volume_both_component },
+    { countof(mic_privacy_component), mic_privacy_component },
 };
 
 zx_status_t astro_buttons_init(aml_bus_t* bus) {
 
-    zx_status_t status = pbus_device_add(&bus->pbus, &astro_buttons_dev);
+    static pbus_dev_t dev;
+    dev.name = "astro-buttons";
+    dev.vid = PDEV_VID_GENERIC;
+    dev.pid = PDEV_PID_GENERIC;
+    dev.did = PDEV_DID_HID_BUTTONS;
+    dev.metadata_list = available_buttons_metadata;
+    dev.metadata_count = countof(available_buttons_metadata);
+    zx_status_t status = pbus_composite_device_add(&bus->pbus, &dev, components,
+                                                   countof(components), UINT32_MAX);
     if (status != ZX_OK) {
-        zxlogf(ERROR, "%s pbus_device_add failed: %d\n", __FUNCTION__, status);
+        zxlogf(ERROR, "%s: pbus_composite_device_add failed: %d\n", __func__, status);
         return status;
     }
 
diff --git a/zircon/system/dev/board/astro/astro-gpio.c b/zircon/system/dev/board/astro/astro-gpio.c
index 99bd2c2..f8ee181 100644
--- a/zircon/system/dev/board/astro/astro-gpio.c
+++ b/zircon/system/dev/board/astro/astro-gpio.c
@@ -87,6 +87,11 @@
     // For audio.
     { GPIO_AUDIO_SOC_FAULT_L },
     { GPIO_SOC_AUDIO_EN },
+    // For buttons.
+    { GPIO_VOLUME_UP },
+    { GPIO_VOLUME_DOWN },
+    { GPIO_VOLUME_BOTH },
+    { GPIO_MIC_PRIVACY },
 };
 
 static const pbus_metadata_t gpio_metadata[] = {
diff --git a/zircon/system/dev/board/astro/astro-gpios.h b/zircon/system/dev/board/astro/astro-gpios.h
index 84ceeb3..4e28d1c 100644
--- a/zircon/system/dev/board/astro/astro-gpios.h
+++ b/zircon/system/dev/board/astro/astro-gpios.h
@@ -14,3 +14,7 @@
 #define GPIO_LIGHT_INTERRUPT    S905D2_GPIOAO(5)
 #define GPIO_AUDIO_SOC_FAULT_L  S905D2_GPIOA(4)
 #define GPIO_SOC_AUDIO_EN       S905D2_GPIOA(5)
+#define GPIO_VOLUME_UP          S905D2_GPIOZ(5)
+#define GPIO_VOLUME_DOWN        S905D2_GPIOZ(6)
+#define GPIO_VOLUME_BOTH        S905D2_GPIOAO(10)
+#define GPIO_MIC_PRIVACY        S905D2_GPIOZ(2)
diff --git a/zircon/system/dev/board/mt8167s_ref/mt8167-buttons.cc b/zircon/system/dev/board/mt8167s_ref/mt8167-buttons.cc
index e555520..a271059 100644
--- a/zircon/system/dev/board/mt8167s_ref/mt8167-buttons.cc
+++ b/zircon/system/dev/board/mt8167s_ref/mt8167-buttons.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <ddk/binding.h>
 #include <ddk/debug.h>
 #include <ddk/device.h>
 #include <ddk/metadata.h>
@@ -16,26 +17,6 @@
 namespace board_mt8167 {
 
 zx_status_t Mt8167::ButtonsInit() {
-
-    // MT8167S_REF
-    constexpr pbus_gpio_t mt8167s_ref_pbus_gpios[] = {
-        {
-            // KPROW0.
-            .gpio = 40,
-        },
-        {
-            // KPROW1.
-            .gpio = 41,
-        },
-        {
-            // KPCOL0.
-            .gpio = 42,
-        },
-        {
-            // KPCOL1.
-            .gpio = 43,
-        },
-    };
     // clang-format off
     static constexpr buttons_button_config_t mt8167s_ref_buttons[] = {
         {BUTTONS_TYPE_MATRIX, BUTTONS_ID_VOLUME_UP,  0, 2, 0},
@@ -63,17 +44,6 @@
         }
     };
 
-    // Cleo
-    constexpr pbus_gpio_t cleo_pbus_gpios[] = {
-        {
-            // VOL+. TODO(andresoportus) plumb VOL- through PMIC.
-            .gpio = 42,
-        },
-        {
-            // MUTE_MIC.
-            .gpio = 23,
-        },
-    };
     static constexpr buttons_button_config_t cleo_buttons[] = {
         {BUTTONS_TYPE_DIRECT, BUTTONS_ID_VOLUME_UP, 0, 0, 0},
         {BUTTONS_TYPE_DIRECT, BUTTONS_ID_MIC_MUTE, 1, 0, 0},
@@ -100,26 +70,87 @@
     dev.vid = PDEV_VID_GENERIC;
     dev.pid = PDEV_PID_GENERIC;
     dev.did = PDEV_DID_HID_BUTTONS;
+    static const zx_bind_inst_t root_match[] = {
+        BI_MATCH(),
+    };
     if (board_info_.vid == PDEV_VID_MEDIATEK && board_info_.pid == PDEV_PID_MEDIATEK_8167S_REF) {
-        dev.gpio_list = mt8167s_ref_pbus_gpios;
-        dev.gpio_count = countof(mt8167s_ref_pbus_gpios);
         dev.metadata_list = mt8167s_ref_metadata;
         dev.metadata_count = countof(mt8167s_ref_metadata);
+        static const zx_bind_inst_t row0_match[] = {
+            BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+            BI_MATCH_IF(EQ, BIND_GPIO_PIN, MT8167_GPIO_KP_ROW0),
+        };
+        static const zx_bind_inst_t row1_match[] = {
+            BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+            BI_MATCH_IF(EQ, BIND_GPIO_PIN, MT8167_GPIO_KP_ROW1),
+        };
+        static const zx_bind_inst_t col0_match[] = {
+            BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+            BI_MATCH_IF(EQ, BIND_GPIO_PIN, MT8167_GPIO_KP_COL0),
+        };
+        static const zx_bind_inst_t col1_match[] = {
+            BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+            BI_MATCH_IF(EQ, BIND_GPIO_PIN, MT8167_GPIO_KP_COL1),
+        };
+        static const device_component_part_t row0_component[] = {
+            { countof(root_match), root_match },
+            { countof(row0_match), row0_match },
+        };
+        static const device_component_part_t row1_component[] = {
+            { countof(root_match), root_match },
+            { countof(row1_match), row1_match },
+        };
+        static const device_component_part_t col0_component[] = {
+            { countof(root_match), root_match },
+            { countof(col0_match), col0_match },
+        };
+        static const device_component_part_t col1_component[] = {
+            { countof(root_match), root_match },
+            { countof(col1_match), col1_match },
+        };
+        static const device_component_t components[] = {
+            { countof(row0_component), row0_component },
+            { countof(row1_component), row1_component },
+            { countof(col0_component), col0_component },
+            { countof(col0_component), col1_component },
+        };
+        auto status = pbus_.CompositeDeviceAdd(&dev, components, countof(components), UINT32_MAX);
+        if (status != ZX_OK) {
+            zxlogf(ERROR, "%s: CompositeDeviceAdd failed %d\n", __FUNCTION__, status);
+            return status;
+        }
     } else if (board_info_.vid == PDEV_VID_GOOGLE && board_info_.pid == PDEV_PID_CLEO) {
-        dev.gpio_list = cleo_pbus_gpios;
-        dev.gpio_count = countof(cleo_pbus_gpios);
         dev.metadata_list = cleo_metadata;
         dev.metadata_count = countof(cleo_metadata);
+        static const zx_bind_inst_t volume_up_match[] = {
+            BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+            BI_MATCH_IF(EQ, BIND_GPIO_PIN, MT8167_GPIO_VOLUME_UP),
+        };
+        static const zx_bind_inst_t mic_privacy_match[] = {
+            BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+            BI_MATCH_IF(EQ, BIND_GPIO_PIN, MT8167_GPIO_MIC_PRIVACY),
+        };
+        static const device_component_part_t volume_up_component[] = {
+            { countof(root_match), root_match },
+            { countof(volume_up_match), volume_up_match },
+        };
+        static const device_component_part_t mic_privacy_component[] = {
+            { countof(root_match), root_match },
+            { countof(mic_privacy_match), mic_privacy_match },
+        };
+        static const device_component_t components[] = {
+            { countof(volume_up_component), volume_up_component },
+            { countof(mic_privacy_component), mic_privacy_component },
+        };
+        auto status = pbus_.CompositeDeviceAdd(&dev, components, countof(components), UINT32_MAX);
+        if (status != ZX_OK) {
+            zxlogf(ERROR, "%s: CompositeDeviceAdd failed %d\n", __FUNCTION__, status);
+            return status;
+        }
     } else {
         return ZX_ERR_NOT_SUPPORTED;
     }
 
-    zx_status_t status = pbus_.DeviceAdd(&dev);
-    if (status != ZX_OK) {
-        zxlogf(ERROR, "%s: pbus_.DeviceAdd failed %d\n", __FUNCTION__, status);
-        return status;
-    }
-
     return ZX_OK;
 }
 
diff --git a/zircon/system/dev/board/mt8167s_ref/mt8167-gpio.cc b/zircon/system/dev/board/mt8167s_ref/mt8167-gpio.cc
index d72e3d1..a910486 100644
--- a/zircon/system/dev/board/mt8167s_ref/mt8167-gpio.cc
+++ b/zircon/system/dev/board/mt8167s_ref/mt8167-gpio.cc
@@ -52,6 +52,14 @@
         { MT8167_GPIO108_MSDC1_DAT2 },
         // For audio in
         { MT8167_GPIO24_EINT24 },
+        // For mt8167 buttons.
+        { MT8167_GPIO_KP_ROW0 },
+        { MT8167_GPIO_KP_ROW1 },
+        { MT8167_GPIO_KP_COL0 },
+        { MT8167_GPIO_KP_COL1 },
+        // For cleo buttons.
+        { MT8167_GPIO_VOLUME_UP },
+        { MT8167_GPIO_MIC_PRIVACY },
     };
 
     const pbus_metadata_t cleo_gpio_metadata[] = {
diff --git a/zircon/system/dev/board/sherlock/sherlock-buttons.cc b/zircon/system/dev/board/sherlock/sherlock-buttons.cc
index c558c37..8a0e3f0 100644
--- a/zircon/system/dev/board/sherlock/sherlock-buttons.cc
+++ b/zircon/system/dev/board/sherlock/sherlock-buttons.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <ddk/binding.h>
 #include <ddk/debug.h>
 #include <ddk/device.h>
 #include <ddk/metadata.h>
@@ -11,28 +12,52 @@
 #include <soc/aml-t931/t931-gpio.h>
 #include <soc/aml-t931/t931-hw.h>
 
+#include "sherlock-gpios.h"
 #include "sherlock.h"
 
 namespace sherlock {
 
 zx_status_t Sherlock::ButtonsInit() {
-    constexpr pbus_gpio_t sherlock_buttons_gpios[] = {
-        {
-            // Volume up.
-            .gpio = T931_GPIOZ(4),
-        },
-        {
-            // Volume down.
-            .gpio = T931_GPIOZ(5),
-        },
-        {
-            // Both Volume up and down pressed.
-            .gpio = T931_GPIOZ(13),
-        },
-        {
-            // Mic privacy switch.
-            .gpio = T931_GPIOH(3),
-        },
+    static const zx_bind_inst_t root_match[] = {
+        BI_MATCH(),
+    };
+    static const zx_bind_inst_t volume_up_match[] = {
+        BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+        BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_VOLUME_UP),
+    };
+    static const zx_bind_inst_t volume_down_match[] = {
+        BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+        BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_VOLUME_DOWN),
+    };
+    static const zx_bind_inst_t volume_both_match[] = {
+        BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+        BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_VOLUME_BOTH),
+    };
+    static const zx_bind_inst_t mic_privacy_match[] = {
+        BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+        BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_MIC_PRIVACY),
+    };
+    static const device_component_part_t volume_up_component[] = {
+        { countof(root_match), root_match },
+        { countof(volume_up_match), volume_up_match },
+    };
+    static const device_component_part_t volume_down_component[] = {
+        { countof(root_match), root_match },
+        { countof(volume_down_match), volume_down_match },
+    };
+    static const device_component_part_t volume_both_component[] = {
+        { countof(root_match), root_match },
+        { countof(volume_both_match), volume_both_match },
+    };
+    static const device_component_part_t mic_privacy_component[] = {
+        { countof(root_match), root_match },
+        { countof(mic_privacy_match), mic_privacy_match },
+    };
+    static const device_component_t components[] = {
+        { countof(volume_up_component), volume_up_component },
+        { countof(volume_down_component), volume_down_component },
+        { countof(volume_both_component), volume_both_component },
+        { countof(mic_privacy_component), mic_privacy_component },
     };
     // clang-format off
     static constexpr buttons_button_config_t buttons[] = {
@@ -65,14 +90,13 @@
     sherlock_buttons_dev.vid = PDEV_VID_GENERIC;
     sherlock_buttons_dev.pid = PDEV_PID_GENERIC;
     sherlock_buttons_dev.did = PDEV_DID_HID_BUTTONS;
-    sherlock_buttons_dev.gpio_list = sherlock_buttons_gpios;
-    sherlock_buttons_dev.gpio_count = countof(sherlock_buttons_gpios);
     sherlock_buttons_dev.metadata_list = available_buttons_metadata;
     sherlock_buttons_dev.metadata_count = countof(available_buttons_metadata);
 
-    zx_status_t status = pbus_.DeviceAdd(&sherlock_buttons_dev);
+    auto status = pbus_.CompositeDeviceAdd(&sherlock_buttons_dev, components,
+                                                  countof(components), UINT32_MAX);
     if (status != ZX_OK) {
-        zxlogf(ERROR, "%s: pbus_.DeviceAdd failed %d\n", __FUNCTION__, status);
+        zxlogf(ERROR, "%s: CompositeDeviceAdd failed %d\n", __FUNCTION__, status);
         return status;
     }
 
diff --git a/zircon/system/dev/board/sherlock/sherlock-gpio.cc b/zircon/system/dev/board/sherlock/sherlock-gpio.cc
index 82269f9..9748890 100644
--- a/zircon/system/dev/board/sherlock/sherlock-gpio.cc
+++ b/zircon/system/dev/board/sherlock/sherlock-gpio.cc
@@ -87,6 +87,11 @@
     {GPIO_LIGHT_INTERRUPT},
     // For SPI interface.
     {GPIO_SPICC0_SS0},
+    // For buttons.
+    {GPIO_VOLUME_UP},
+    {GPIO_VOLUME_DOWN},
+    {GPIO_VOLUME_BOTH},
+    {GPIO_MIC_PRIVACY},
 };
 
 static const pbus_metadata_t gpio_metadata[] = {
diff --git a/zircon/system/dev/board/sherlock/sherlock-gpios.h b/zircon/system/dev/board/sherlock/sherlock-gpios.h
index d23a1cf..465455a 100644
--- a/zircon/system/dev/board/sherlock/sherlock-gpios.h
+++ b/zircon/system/dev/board/sherlock/sherlock-gpios.h
@@ -18,3 +18,7 @@
 #define GPIO_CAM_RESET          T931_GPIOZ(0)
 #define GPIO_LIGHT_INTERRUPT    T931_GPIOAO(5)
 #define GPIO_SPICC0_SS0         T931_GPIOC(2)
+#define GPIO_VOLUME_UP          T931_GPIOZ(4)
+#define GPIO_VOLUME_DOWN        T931_GPIOZ(5)
+#define GPIO_VOLUME_BOTH        T931_GPIOZ(13)
+#define GPIO_MIC_PRIVACY        T931_GPIOH(3)
diff --git a/zircon/system/dev/input/hid-buttons/BUILD.gn b/zircon/system/dev/input/hid-buttons/BUILD.gn
index 7f1434d..3d792db 100644
--- a/zircon/system/dev/input/hid-buttons/BUILD.gn
+++ b/zircon/system/dev/input/hid-buttons/BUILD.gn
@@ -7,10 +7,9 @@
     "hid-buttons.cc",
   ]
   deps = [
+    "$zx/system/banjo/ddk.protocol.composite",
     "$zx/system/banjo/ddk.protocol.gpio",
     "$zx/system/banjo/ddk.protocol.hidbus",
-    "$zx/system/banjo/ddk.protocol.platform.bus",
-    "$zx/system/banjo/ddk.protocol.platform.device",
     "$zx/system/ulib/ddk",
     "$zx/system/ulib/ddktl",
     "$zx/system/ulib/fbl",
@@ -31,10 +30,9 @@
     "hid-buttons.cc",
   ]
   deps = [
+    "$zx/system/banjo/ddk.protocol.composite",
     "$zx/system/banjo/ddk.protocol.gpio",
     "$zx/system/banjo/ddk.protocol.hidbus",
-    "$zx/system/banjo/ddk.protocol.platform.bus",
-    "$zx/system/banjo/ddk.protocol.platform.device",
     "$zx/system/dev/lib/fake_ddk",
     "$zx/system/ulib/ddk",
     "$zx/system/ulib/ddktl",
diff --git a/zircon/system/dev/input/hid-buttons/hid-buttons-test.cc b/zircon/system/dev/input/hid-buttons/hid-buttons-test.cc
index 6f1e2f3..2c43286 100644
--- a/zircon/system/dev/input/hid-buttons/hid-buttons-test.cc
+++ b/zircon/system/dev/input/hid-buttons/hid-buttons-test.cc
@@ -6,7 +6,6 @@
 
 #include <ddk/metadata.h>
 #include <ddk/metadata/buttons.h>
-#include <ddk/protocol/platform/bus.h>
 #include <ddktl/protocol/gpio.h>
 #include <lib/fake_ddk/fake_ddk.h>
 #include <mock/ddktl/protocol/gpio.h>
diff --git a/zircon/system/dev/input/hid-buttons/hid-buttons.cc b/zircon/system/dev/input/hid-buttons/hid-buttons.cc
index 38fbf71..7eb2285 100644
--- a/zircon/system/dev/input/hid-buttons/hid-buttons.cc
+++ b/zircon/system/dev/input/hid-buttons/hid-buttons.cc
@@ -12,8 +12,7 @@
 #include <ddk/debug.h>
 #include <ddk/metadata.h>
 #include <ddk/platform-defs.h>
-#include <ddk/protocol/platform/bus.h>
-#include <ddk/protocol/platform/device.h>
+#include <ddktl/protocol/composite.h>
 #include <fbl/algorithm.h>
 #include <fbl/auto_call.h>
 #include <fbl/auto_lock.h>
@@ -338,16 +337,9 @@
         return ZX_ERR_NO_MEMORY;
     }
 
-    pdev_protocol_t pdev;
-    auto status = device_get_protocol(parent, ZX_PROTOCOL_PDEV, &pdev);
-    if (status != ZX_OK) {
-        zxlogf(ERROR, "%s device_get_protocol failed %d\n", __FUNCTION__, status);
-        return status;
-    }
-
     // Get buttons metadata.
     size_t actual = 0;
-    status = device_get_metadata_size(parent, DEVICE_METADATA_BUTTONS_BUTTONS, &actual);
+    auto status = device_get_metadata_size(parent, DEVICE_METADATA_BUTTONS_BUTTONS, &actual);
     if (status != ZX_OK) {
         zxlogf(ERROR, "%s device_get_metadata_size failed %d\n", __FILE__, status);
         return ZX_OK;
@@ -385,16 +377,34 @@
         return status;
     }
 
+    // Get the GPIOs.
+    ddk::CompositeProtocolClient composite(parent);
+    if (!composite.is_valid()) {
+        zxlogf(ERROR, "HidButtonsDevice: Could not get composite protocol\n");
+        return ZX_ERR_NOT_SUPPORTED;
+    }
+
+    // component 0 is platform device, only used for passing metadata.
+    auto component_count = composite.GetComponentCount();
+    if (component_count != n_gpios + 1) {
+        zxlogf(ERROR, "%s Could not get composite protocol\n", __func__);
+        return ZX_ERR_INTERNAL;
+    }
+    zx_device_t* components[component_count];
+    composite.GetComponents(components, component_count, &actual);
+    if (actual != component_count) {
+        return ZX_ERR_INTERNAL;
+    }
+
     // Prepare gpios array.
     auto gpios = fbl::Array(new (&ac) HidButtonsDevice::Gpio[n_gpios], n_gpios);
     if (!ac.check()) {
         return ZX_ERR_NO_MEMORY;
     }
     for (uint32_t i = 0; i < n_gpios; ++i) {
-        size_t actual = 0;
-        status = pdev_get_protocol(&pdev, ZX_PROTOCOL_GPIO, i, &gpios[i].gpio,
-                                   sizeof(gpio_protocol_t), &actual);
-        if (status != ZX_OK || sizeof(gpio_protocol_t) != actual) {
+        status = device_get_protocol(components[i + 1], ZX_PROTOCOL_GPIO, &gpios[i].gpio);
+        if (status != ZX_OK) {
+            zxlogf(ERROR, "%s Could not get protocol\n", __func__);
             return ZX_ERR_INTERNAL;
         }
         gpios[i].config = gpios_configs[i];
@@ -419,7 +429,8 @@
 } // namespace buttons
 
 // clang-format off
-ZIRCON_DRIVER_BEGIN(hid_buttons, buttons::hid_buttons_driver_ops, "zircon", "0.1", 3)
+ZIRCON_DRIVER_BEGIN(hid_buttons, buttons::hid_buttons_driver_ops, "zircon", "0.1", 4)
+    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_COMPOSITE),
     BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_GENERIC),
     BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_GENERIC),
     BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_HID_BUTTONS),
diff --git a/zircon/system/dev/input/hid-buttons/hid-buttons.h b/zircon/system/dev/input/hid-buttons/hid-buttons.h
index af4085f..1d1c45f 100644
--- a/zircon/system/dev/input/hid-buttons/hid-buttons.h
+++ b/zircon/system/dev/input/hid-buttons/hid-buttons.h
@@ -6,7 +6,6 @@
 
 #include <ddk/metadata/buttons.h>
 #include <ddk/protocol/gpio.h>
-#include <ddk/protocol/platform/device.h>
 #include <ddktl/device.h>
 #include <ddktl/protocol/hidbus.h>
 #include <fbl/array.h>
diff --git a/zircon/system/dev/lib/mt8167/include/soc/mt8167/mt8167-hw.h b/zircon/system/dev/lib/mt8167/include/soc/mt8167/mt8167-hw.h
index 3b45146..6956464 100644
--- a/zircon/system/dev/lib/mt8167/include/soc/mt8167/mt8167-hw.h
+++ b/zircon/system/dev/lib/mt8167/include/soc/mt8167/mt8167-hw.h
@@ -140,8 +140,13 @@
 #define MT8167_GPIO_MT7668_PMU_EN                           2
 #define MT8167_GPIO_TOUCH_INT                               8
 #define MT8167_GPIO_TOUCH_RST                               9
+#define MT8167_GPIO_MIC_PRIVACY                             23
+#define MT8167_GPIO_KP_ROW0                                 40
+#define MT8167_GPIO_KP_ROW1                                 41
+#define MT8167_GPIO_KP_COL0                                 42
+#define MT8167_GPIO_VOLUME_UP                               42
+#define MT8167_GPIO_KP_COL1                                 43
 #define MT8167_GPIO_LCD_RST                                 66
 #define MT8167_GPIO_MSDC0_RST                               114
-
 #define MT8167_CLEO_GPIO_HUB_PWR_EN                         13
 #define MT8167_CLEO_GPIO_LCM_EN                             22
diff --git a/zircon/system/utest/device-enumeration/main.cc b/zircon/system/utest/device-enumeration/main.cc
index 5d40a9a..883cb8d 100644
--- a/zircon/system/utest/device-enumeration/main.cc
+++ b/zircon/system/utest/device-enumeration/main.cc
@@ -125,7 +125,7 @@
     static const char* kDevicePaths[] = {
         "sys/platform/aml-bus",
         "sys/platform/05:03:1/aml-axg-gpio",
-        "sys/platform/00:00:13/hid-buttons/hid-device-000",
+        "astro-buttons/hid-buttons",
         "sys/platform/05:00:2/aml-i2c",
         "sys/platform/05:03:17/aml-gpu",
         "sys/platform/05:00:18/aml-usb-phy-v2",
@@ -149,8 +149,6 @@
         "sys/platform/05:00:f/aml-raw_nand/nand/zircon-b/skip-block",
         "sys/platform/05:00:f/aml-raw_nand/nand/zircon-a/skip-block",
         "sys/platform/05:00:f/aml-raw_nand/nand/zircon-r/skip-block",
-        "sys/platform/05:00:f/aml-raw_nand/nand/fvm/ftl/block/fvm/blobfs-p-1/block",
-        "sys/platform/05:00:f/aml-raw_nand/nand/fvm/ftl/block/fvm/minfs-p-2/block/zxcrypt/unsealed/block",
         "sys/platform/05:00:f/aml-raw_nand/nand/sys-config/skip-block",
         "sys/platform/05:00:f/aml-raw_nand/nand/migration/skip-block",
         "sys/platform/05:00:7/aml-sd-emmc/sdmmc",