static bt_status_t
get_remote_device_properties(const struct pdu* cmd)
{
  bt_bdaddr_t remote_addr;
  struct pdu_wbuf* wbuf;
  int status;

  assert(bt_interface);
  assert(bt_interface->get_remote_device_properties);

  if (read_bt_bdaddr_t(cmd, 0, &remote_addr) < 0)
    return BT_STATUS_PARM_INVALID;

  wbuf = create_pdu_wbuf(0, 0, NULL);
  if (!wbuf)
    return BT_STATUS_NOMEM;

  status = bt_interface->get_remote_device_properties(&remote_addr);
  if (status != BT_STATUS_SUCCESS)
    goto err_bt_interface_get_remote_device_properties;

  init_pdu(&wbuf->buf.pdu, cmd->service, cmd->opcode);
  send_pdu(wbuf);

  return BT_STATUS_SUCCESS;
err_bt_interface_get_remote_device_properties:
  cleanup_pdu_wbuf(wbuf);
  return status;
}
static bt_status_t
get_remote_device_property(const struct pdu* cmd)
{
  long off;
  bt_bdaddr_t remote_addr;
  uint8_t type;
  struct pdu_wbuf* wbuf;
  int status;

  assert(bt_interface);
  assert(bt_interface->get_remote_device_property);

  off = read_bt_bdaddr_t(cmd, 0, &remote_addr);
  if (off < 0)
    return BT_STATUS_PARM_INVALID;
  if (read_pdu_at(cmd, off, "C", &type) < 0)
    return BT_STATUS_PARM_INVALID;

  wbuf = create_pdu_wbuf(0, 0, NULL);
  if (!wbuf)
    return BT_STATUS_NOMEM;

  status = bt_interface->get_remote_device_property(&remote_addr, type);
  if (status != BT_STATUS_SUCCESS)
    goto err_bt_interface_get_remote_device_property;

  init_pdu(&wbuf->buf.pdu, cmd->service, cmd->opcode);
  send_pdu(wbuf);

  return BT_STATUS_SUCCESS;
err_bt_interface_get_remote_device_property:
  cleanup_pdu_wbuf(wbuf);
  return status;
}
static bt_status_t
cancel_bond(const struct pdu* cmd)
{
  bt_bdaddr_t bd_addr;
  struct pdu_wbuf* wbuf;
  int status;

  assert(bt_interface);
  assert(bt_interface->cancel_bond);

  if (read_bt_bdaddr_t(cmd, 0, &bd_addr) < 0)
    return BT_STATUS_PARM_INVALID;

  wbuf = create_pdu_wbuf(0, 0, NULL);
  if (!wbuf)
    return BT_STATUS_NOMEM;

  status = bt_interface->cancel_bond(&bd_addr);
  if (status != BT_STATUS_SUCCESS)
    goto err_bt_interface_cancel_bond;

  init_pdu(&wbuf->buf.pdu, cmd->service, cmd->opcode);
  send_pdu(wbuf);

  return BT_STATUS_SUCCESS;
err_bt_interface_cancel_bond:
  cleanup_pdu_wbuf(wbuf);
  return status;
}
static bt_status_t
create_bond(const struct pdu* cmd)
{
  long off;
  bt_bdaddr_t bd_addr;
  struct pdu_wbuf* wbuf;
  int status;
#if ANDROID_VERSION >= 21
  uint8_t transport;
#endif

  assert(bt_interface);
  assert(bt_interface->create_bond);

  off = read_bt_bdaddr_t(cmd, 0, &bd_addr);
  if (off < 0)
    return BT_STATUS_PARM_INVALID;

#if ANDROID_VERSION >= 21
  if (read_pdu_at(cmd, off, "C", &transport) < 0)
    return BT_STATUS_PARM_INVALID;
#endif

  wbuf = create_pdu_wbuf(0, 0, NULL);
  if (!wbuf)
    return BT_STATUS_NOMEM;

#if ANDROID_VERSION >= 21
  status = bt_interface->create_bond(&bd_addr, transport);
#else
  status = bt_interface->create_bond(&bd_addr);
#endif
  if (status != BT_STATUS_SUCCESS)
    goto err_bt_interface_create_bond;

  init_pdu(&wbuf->buf.pdu, cmd->service, cmd->opcode);
  send_pdu(wbuf);

  return BT_STATUS_SUCCESS;
err_bt_interface_create_bond:
  cleanup_pdu_wbuf(wbuf);
  return status;
}
static bt_status_t
get_remote_service_record(const struct pdu* cmd)
{
  long off;
  bt_bdaddr_t remote_addr;
  bt_uuid_t uuid;
  struct pdu_wbuf* wbuf;
  struct get_remote_service_record_params* params;
  int status;

  assert(bt_interface);
  assert(bt_interface->get_remote_service_record);

  off = read_bt_bdaddr_t(cmd, 0, &remote_addr);
  if (off < 0)
    return BT_STATUS_PARM_INVALID;
  if (read_bt_uuid_t(cmd, off, &uuid) < 0)
    return BT_STATUS_PARM_INVALID;

  wbuf = create_pdu_wbuf(0, 0, NULL);
  if (!wbuf)
    return BT_STATUS_NOMEM;

  params = store_get_remote_service_record_params(&remote_addr, &uuid);
  if (!params) {
    status = BT_STATUS_NOMEM;
    goto err_store_get_remote_service_record_params;
  }

  status = bt_interface->get_remote_service_record(&remote_addr, &uuid);
  if (status != BT_STATUS_SUCCESS)
    goto err_bt_interface_get_remote_service_record;

  init_pdu(&wbuf->buf.pdu, cmd->service, cmd->opcode);
  send_pdu(wbuf);

  return BT_STATUS_SUCCESS;
err_bt_interface_get_remote_service_record:
  remove_get_remote_service_record_params(params);
err_store_get_remote_service_record_params:
  cleanup_pdu_wbuf(wbuf);
  return status;
}
static bt_status_t
opcode_connect(const struct pdu* cmd)
{
  long off;
  bt_bdaddr_t bd_addr;
  uint8_t type;
  uint8_t uuid[16];
  uint16_t channel;
  uint8_t flags;
  struct pdu_wbuf* wbuf;
  struct ancillary_data* data;
  bt_status_t status;

  off = read_bt_bdaddr_t(cmd, 0, &bd_addr);
  if (off < 0)
    return BT_STATUS_PARM_INVALID;
  if (read_pdu_at(cmd, off, "CmsC", &type, uuid, sizeof(uuid),
                                    &channel, &flags) < 0)
    return BT_STATUS_PARM_INVALID;

  wbuf = create_pdu_wbuf(0,
                         ALIGNMENT_PADDING + sizeof(*data),
                         build_ancillary_data);
  if (!wbuf)
    return BT_STATUS_NOMEM;

  data = ceil_align(pdu_wbuf_tail(wbuf), ALIGNMENT_PADDING);

  status = bt_sock_connect(&bd_addr, type, uuid, channel,
                           &data->sock_fd, flags);
  if (status != BT_STATUS_SUCCESS)
    goto err_bt_sock_listen;

  init_pdu(&wbuf->buf.pdu, cmd->service, cmd->opcode);
  send_pdu(wbuf);

  return BT_STATUS_SUCCESS;
err_bt_sock_listen:
  cleanup_pdu_wbuf(wbuf);
  return status;
}
static bt_status_t
set_remote_device_property(const struct pdu* cmd)
{
  long off;
  bt_bdaddr_t remote_addr;
  bt_property_t property;
  struct pdu_wbuf* wbuf;
  int status;

  assert(bt_interface);
  assert(bt_interface->set_remote_device_property);

  off = read_bt_bdaddr_t(cmd, 0, &remote_addr);
  if (off < 0)
    return BT_STATUS_PARM_INVALID;
  if (read_bt_property_t(cmd, off, &property) < 0)
    return BT_STATUS_PARM_INVALID;

  wbuf = create_pdu_wbuf(0, 0, NULL);
  if (!wbuf) {
    status = BT_STATUS_NOMEM;
    goto err_create_pdu_wbuf;
  }

  status = bt_interface->set_remote_device_property(&remote_addr, &property);
  if (status != BT_STATUS_SUCCESS)
    goto err_bt_interface_set_remote_device_property;

  free(property.val);

  init_pdu(&wbuf->buf.pdu, cmd->service, cmd->opcode);
  send_pdu(wbuf);

  return BT_STATUS_SUCCESS;
err_bt_interface_set_remote_device_property:
  cleanup_pdu_wbuf(wbuf);
err_create_pdu_wbuf:
  free(property.val);
  return status;
}
static bt_status_t
pin_reply(const struct pdu* cmd)
{
  long off;
  bt_bdaddr_t bd_addr;
  uint8_t accept;
  uint8_t pin_len;
  bt_pin_code_t pin_code;
  struct pdu_wbuf* wbuf;
  int status;

  assert(bt_interface);
  assert(bt_interface->pin_reply);

  off = read_bt_bdaddr_t(cmd, 0, &bd_addr);
  if (off < 0)
    return BT_STATUS_PARM_INVALID;
  off = read_pdu_at(cmd, off, "CC", &accept, &pin_len);
  if (off < 0)
    return BT_STATUS_PARM_INVALID;
  if (read_bt_pin_code_t(cmd, off, &pin_code) < 0)
    return BT_STATUS_PARM_INVALID;

  wbuf = create_pdu_wbuf(0, 0, NULL);
  if (!wbuf)
    return BT_STATUS_NOMEM;

  status = bt_interface->pin_reply(&bd_addr, accept, pin_len, &pin_code);
  if (status != BT_STATUS_SUCCESS)
    goto err_bt_interface_pin_reply;

  init_pdu(&wbuf->buf.pdu, cmd->service, cmd->opcode);
  send_pdu(wbuf);

  return BT_STATUS_SUCCESS;
err_bt_interface_pin_reply:
  cleanup_pdu_wbuf(wbuf);
  return status;
}
Exemplo n.º 9
0
static bt_status_t
opcode_connect(const struct pdu* cmd)
{
  long off;
  bt_bdaddr_t bd_addr;
  uint8_t type;
  uint8_t uuid[16];
  uint16_t channel;
  uint8_t flags;
  int sock_fd;
  struct pdu_wbuf* wbuf;
  bt_status_t status;

  off = read_bt_bdaddr_t(cmd, 0, &bd_addr);
  if (off < 0)
    return BT_STATUS_PARM_INVALID;
  if (read_pdu_at(cmd, off, "CmSC", &type, uuid, (size_t)uuid,
                                   &channel, &flags) < 0)
    return BT_STATUS_PARM_INVALID;

  wbuf = create_pdu_wbuf(0, sizeof(*wbuf->msg.msg_iov));
  if (!wbuf)
    return BT_STATUS_NOMEM;

  status = bt_sock_connect(&bd_addr, type, uuid, channel, &sock_fd, flags);
  if (status != BT_STATUS_SUCCESS)
    goto err_bt_sock_listen;

  init_pdu(&wbuf->buf.pdu, cmd->service, cmd->opcode);
  send_pdu(build_pdu_wbuf_msg_with_fd(wbuf, sock_fd));

  return BT_STATUS_SUCCESS;
err_bt_sock_listen:
  cleanup_pdu_wbuf(wbuf);
  return status;
}