static void
acl_state_changed_cb(bt_status_t status, bt_bdaddr_t* remote_bd_addr,
                     bt_acl_state_t state)
{
  struct pdu_wbuf* wbuf;

  wbuf = create_pdu_wbuf(1 + /* status */
                         6 + /* remote address */
                         1, /* ACL state */
                         0, NULL);
  if (!wbuf)
    return;

  init_pdu(&wbuf->buf.pdu, SERVICE_BT_CORE, OPCODE_ACL_STATE_CHANGED_NTF);
  if (append_to_pdu(&wbuf->buf.pdu, "C", (uint8_t)status) < 0)
    goto cleanup;
  if (append_bt_bdaddr_t(&wbuf->buf.pdu, remote_bd_addr) < 0)
    goto cleanup;
  if (append_to_pdu(&wbuf->buf.pdu, "C", (uint8_t)state) < 0)
    goto cleanup;

  if (run_task(send_ntf_pdu, wbuf) < 0)
    goto cleanup;

  return;
cleanup:
  cleanup_pdu_wbuf(wbuf);
}
static void
pin_request_cb(bt_bdaddr_t* remote_bd_addr, bt_bdname_t* bd_name,
               uint32_t cod)
{
  struct pdu_wbuf* wbuf;

  wbuf = create_pdu_wbuf(6 + /* remote address */
                         249 + /* remote name */
                         4, /* class of device */
                         0, NULL);
  if (!wbuf)
    return;

  init_pdu(&wbuf->buf.pdu, SERVICE_BT_CORE, OPCODE_PIN_REQUEST_NTF);
  if (append_bt_bdaddr_t(&wbuf->buf.pdu, remote_bd_addr) < 0)
    goto cleanup;
  if (append_bt_bdname_t(&wbuf->buf.pdu, bd_name) < 0)
    goto cleanup;
  if (append_to_pdu(&wbuf->buf.pdu, "I", cod) < 0)
    goto cleanup;

  if (run_task(send_ntf_pdu, wbuf) < 0)
    goto cleanup;

  return;
cleanup:
  cleanup_pdu_wbuf(wbuf);
}
static void
ssp_request_cb(bt_bdaddr_t* remote_bd_addr, bt_bdname_t* bd_name,
               uint32_t cod, bt_ssp_variant_t pairing_variant,
               uint32_t pass_key)
{
  struct pdu_wbuf* wbuf;

  wbuf = create_pdu_wbuf(6 + /* remote address */
                         249 + /* remote name */
                         4 + /* class of device */
                         1 + /* paring variant */
                         4, /* passkey */
                         0, NULL);
  if (!wbuf)
    return;

  init_pdu(&wbuf->buf.pdu, SERVICE_BT_CORE, OPCODE_SSP_REQUEST_NTF);
  if (append_bt_bdaddr_t(&wbuf->buf.pdu, remote_bd_addr) < 0)
    goto cleanup;
  if (append_bt_bdname_t(&wbuf->buf.pdu, bd_name) < 0)
    goto cleanup;
  if (append_to_pdu(&wbuf->buf.pdu, "ICI", cod,
                    (uint8_t)pairing_variant, pass_key) < 0)
    goto cleanup;

  if (run_task(send_ntf_pdu, wbuf) < 0)
    goto cleanup;

  return;
cleanup:
  cleanup_pdu_wbuf(wbuf);
}
static void
remote_device_properties_cb(bt_status_t status,
                            bt_bdaddr_t* bd_addr,
                            int num_properties,
                            bt_property_t* properties)
{
  bt_property_t* aligned_properties;
  struct pdu_wbuf* wbuf;

  properties = align_properties(properties, num_properties,
                                &aligned_properties);
  if (!properties)
    return;

  fix_properties(bd_addr, num_properties, properties);

  wbuf = create_pdu_wbuf(1 + /* status */
                         6 + /* address */
                         1 + /* number of properties */
                         properties_length(num_properties, properties),
                         0, NULL);
  if (!wbuf)
    goto cleanup_properties;

  init_pdu(&wbuf->buf.pdu, SERVICE_BT_CORE,
           OPCODE_REMOTE_DEVICE_PROPERTIES_NTF);
  if (append_to_pdu(&wbuf->buf.pdu, "C", (uint8_t)status) < 0)
    goto cleanup;
  if (append_bt_bdaddr_t(&wbuf->buf.pdu, bd_addr) < 0)
    goto cleanup;
  if (append_bt_property_t_array(&wbuf->buf.pdu,
                                 properties, num_properties) < 0)
    goto cleanup;

  if (run_task(send_ntf_pdu, wbuf) < 0)
    goto cleanup;

  free(aligned_properties);

  return;
cleanup:
  cleanup_pdu_wbuf(wbuf);
cleanup_properties:
  free(aligned_properties);
}
static void
remote_features_cb(bt_bdaddr_t* bd_addr, btrc_remote_features_t features)
{
  struct pdu_wbuf* wbuf;

  wbuf = create_pdu_wbuf(6 + /* address */
                         1, /* feature bitmask */
                         0, NULL);
  if (!wbuf)
    return;

  init_pdu(&wbuf->buf.pdu, SERVICE_BT_RC, OPCODE_REMOTE_FEATURES_NTF);
  if ((append_bt_bdaddr_t(&wbuf->buf.pdu, bd_addr) < 0) ||
      (append_to_pdu(&wbuf->buf.pdu, "C", (uint8_t)features) < 0))
    goto cleanup;

  if (run_task(send_ntf_pdu, wbuf) < 0)
    goto cleanup;

  return;
cleanup:
  cleanup_pdu_wbuf(wbuf);
}