int hci_le_read_local_version(uint8_t *hci_version, uint16_t *hci_revision, uint8_t *lmp_pal_version, uint16_t *manufacturer_name, uint16_t *lmp_pal_subversion) { struct hci_request rq; read_local_version_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_INFO_PARAM; rq.ocf = OCF_READ_LOCAL_VERSION; rq.cparam = NULL; rq.clen = 0; rq.rparam = &resp; rq.rlen = READ_LOCAL_VERSION_RP_SIZE; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; if (resp.status) { return resp.status; } *hci_version = resp.hci_version; *hci_revision = btohs(resp.hci_revision); *lmp_pal_version = resp.lmp_pal_version; *manufacturer_name = btohs(resp.manufacturer_name); *lmp_pal_subversion = btohs(resp.lmp_pal_subversion); return 0; }
// Set advertising interval to 100 ms // Note: 0x00A0 * 0.625ms = 100ms int hci_le_set_advertising_parameters(int dd, int to) { struct hci_request rq; le_set_advertising_parameters_cp adv_params_cp; uint8_t status; memset(&adv_params_cp, 0, sizeof(adv_params_cp)); adv_params_cp.min_interval = htobs(0x00A0); adv_params_cp.max_interval = htobs(0x00A0); adv_params_cp.advtype = 3; adv_params_cp.chan_map = 7; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_ADVERTISING_PARAMETERS; rq.cparam = &adv_params_cp; rq.clen = LE_SET_ADVERTISING_PARAMETERS_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(dd, &rq, to) < 0) return -1; if (status) { errno = EIO; return -1; } return 0; }
int hci_le_test_end(uint16_t *num_pkts) { struct hci_request rq; le_test_end_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_TEST_END; rq.rparam = &resp; rq.rlen = LE_TEST_END_RP_SIZE; if (hci_send_req(&rq, FALSE) < 0){ return BLE_STATUS_TIMEOUT; } if (resp.status) { return resp.status; } *num_pkts = resp.num_pkts; return 0; }
int hci_le_read_supported_states(uint8_t states[8]) { struct hci_request rq; le_read_supported_states_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_READ_SUPPORTED_STATES; rq.rparam = &resp; rq.rlen = LE_READ_SUPPORTED_STATES_RP_SIZE; if (hci_send_req(&rq, FALSE) < 0){ return BLE_STATUS_TIMEOUT; } if (resp.status) { return resp.status; } Osal_MemCpy(states, resp.states, 8); return 0; }
static int brf_send_command_socket(int fd, struct bts_action_send* send_action) { char response[1024] = {0}; hci_command_hdr *cmd = (hci_command_hdr *) send_action->data; uint16_t opcode = cmd->opcode; struct hci_request rq; memset(&rq, 0, sizeof(rq)); rq.ogf = cmd_opcode_ogf(opcode); rq.ocf = cmd_opcode_ocf(opcode); rq.event = EVT_CMD_COMPLETE; rq.cparam = &send_action->data[3]; rq.clen = send_action->data[2]; rq.rparam = response; rq.rlen = sizeof(response); if (hci_send_req(fd, &rq, 15) < 0) { perror("Cannot send hci command to socket"); return -1; } /* verify success */ if (response[0]) { errno = EIO; return -1; } return 0; }
int hci_le_set_scan_response_data(int dd, uint8_t* data, uint8_t length, int to) { struct hci_request rq; le_set_scan_response_data_cp data_cp; uint8_t status; memset(&data_cp, 0, sizeof(data_cp)); data_cp.length = length; memcpy(&data_cp.data, data, sizeof(data_cp.data)); memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_SCAN_RESPONSE_DATA; rq.cparam = &data_cp; rq.clen = LE_SET_SCAN_RESPONSE_DATA_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(dd, &rq, to) < 0) return -1; if (status) { errno = EIO; return -1; } return 0; }
static int do_command(uint16_t command, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length) { unsigned char cp[254], rp[254]; struct hci_request rq; uint8_t cmd[10]; uint16_t size; size = (length < 8) ? 9 : ((length + 1) / 2) + 5; cmd[0] = command & 0xff; cmd[1] = command >> 8; cmd[2] = size & 0xff; cmd[3] = size >> 8; cmd[4] = seqnum & 0xff; cmd[5] = seqnum >> 8; cmd[6] = varid & 0xff; cmd[7] = varid >> 8; cmd[8] = 0x00; cmd[9] = 0x00; memset(cp, 0, sizeof(cp)); cp[0] = 0xc2; memcpy(cp + 1, cmd, sizeof(cmd)); memcpy(cp + 11, value, length); switch (varid) { case CSR_VARID_COLD_RESET: case CSR_VARID_WARM_RESET: case CSR_VARID_COLD_HALT: case CSR_VARID_WARM_HALT: return hci_send_cmd(dd, OGF_VENDOR_CMD, 0x00, (size * 2) + 1, cp); } memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = 0x00; rq.event = EVT_VENDOR; rq.cparam = cp; rq.clen = (size * 2) + 1; rq.rparam = rp; rq.rlen = sizeof(rp); if (hci_send_req(dd, &rq, 2000) < 0) return -1; if (rp[0] != 0xc2) { errno = EIO; return -1; } if ((rp[9] + (rp[10] << 8)) != 0) { errno = ENXIO; return -1; } memcpy(value, rp + 11, length); return 0; }
int HCI::advertisingEnable(uint16_t min_interval, uint16_t max_interval, bool enable) { le_set_advertising_parameters_cp adv_params_cp; memset(&adv_params_cp, 0, sizeof(adv_params_cp)); adv_params_cp.min_interval = util::endian::little(min_interval); adv_params_cp.max_interval = util::endian::little(max_interval); adv_params_cp.chan_map = 7; // All adv channels adv_params_cp.advtype = 0; uint8_t status = 0; hci_request rq; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_ADVERTISING_PARAMETERS; rq.cparam = &adv_params_cp; rq.clen = LE_SET_ADVERTISING_PARAMETERS_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(_hci_sock, &rq, 1000) < 0) { err::code = err::LIB_SYS; return -1; } le_set_advertise_enable_cp advertise_cp; memset(&advertise_cp, 0, sizeof(advertise_cp)); advertise_cp.enable = (uint8_t)(enable ? 0x01 : 0x00); memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE; rq.cparam = &advertise_cp; rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(_hci_sock, &rq, 1000) < 0) { err::code = err::LIB_SYS; return -1; } return 0; }
tBleStatus aci_gatt_include_service(uint16_t service_handle, uint16_t included_start_handle, uint16_t included_end_handle, uint8_t included_uuid_type, const uint8_t* included_uuid, uint16_t *included_handle) { struct hci_request rq; gatt_include_serv_rp resp; uint8_t buffer[23]; uint8_t uuid_len; uint8_t indx = 0; service_handle = htobs(service_handle); memcpy(buffer, &service_handle, 2); indx += 2; included_start_handle = htobs(included_start_handle); memcpy(buffer+indx, &included_start_handle, 2); indx += 2; included_end_handle = htobs(included_end_handle); memcpy(buffer+indx, &included_end_handle, 2); indx += 2; if(included_uuid_type == 0x01){ uuid_len = 2; } else { uuid_len = 16; } buffer[indx] = included_uuid_type; indx++; memcpy(buffer + indx, included_uuid, uuid_len); indx += uuid_len; memset(&resp, 0, sizeof(resp)); memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GATT_INCLUDE_SERV; rq.cparam = (void *)buffer; rq.clen = indx; rq.rparam = &resp; rq.rlen = GATT_INCLUDE_SERV_RP_SIZE; if (hci_send_req(&rq) < 0) return -1; if (resp.status) { return resp.status; } *included_handle = btohs(resp.handle); return 0; }
tBleStatus aci_gatt_discovery_characteristic_by_uuid(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, tHalUint8 charUuidType, const tHalUint8* charUuid) { struct hci_request rq; tHalUint8 status; uint8_t buffer[23]; uint8_t uuid_len; uint8_t indx = 0; conn_handle = htobs(conn_handle); memcpy(buffer + indx, &conn_handle, 2); indx += 2; start_handle = htobs(start_handle); memcpy(buffer + indx, &start_handle, 2); indx += 2; end_handle = htobs(end_handle); memcpy(buffer + indx, &end_handle, 2); indx += 2; buffer[indx] = charUuidType; indx++; if(charUuidType == 0x01){ uuid_len = 2; } else { uuid_len = 16; } memcpy(buffer + indx, charUuid, uuid_len); indx += uuid_len; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GATT_DISC_CHARAC_BY_UUID; rq.cparam = (void *)buffer; rq.clen = indx; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return status; } return 0; }
tBleStatus aci_gatt_set_desc_value(tHalUint16 servHandle, tHalUint16 charHandle, tHalUint16 charDescHandle, tHalUint16 charDescValOffset, tHalUint8 charDescValueLen, const tHalUint8 *charDescValue) { struct hci_request rq; uint8_t status; uint8_t buffer[HCI_MAX_PACKET_SIZE]; uint8_t indx = 0; if ((charDescValueLen+9) > HCI_MAX_PACKET_SIZE) return BLE_STATUS_INVALID_PARAMS; servHandle = htobs(servHandle); memcpy(buffer + indx, &servHandle, 2); indx += 2; charHandle = htobs(charHandle); memcpy(buffer + indx, &charHandle, 2); indx += 2; charDescHandle = htobs(charDescHandle); memcpy(buffer + indx, &charDescHandle, 2); indx += 2; memcpy(buffer + indx, &charDescValOffset, 2); indx += 2; buffer[indx] = charDescValueLen; indx++; memcpy(buffer + indx, charDescValue, charDescValueLen); indx += charDescValueLen; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GATT_SET_DESC_VAL; rq.cparam = (void *)buffer; rq.clen = indx; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return status; } return 0; }
tBleStatus aci_gatt_write_response(uint16_t conn_handle, uint16_t attr_handle, uint8_t write_status, uint8_t err_code, uint8_t att_val_len, uint8_t *att_val) { struct hci_request rq; uint8_t status; uint8_t buffer[HCI_MAX_PACKET_SIZE]; uint8_t indx = 0; if ((att_val_len+7) > HCI_MAX_PACKET_SIZE) return BLE_STATUS_INVALID_PARAMS; conn_handle = htobs(conn_handle); memcpy(buffer + indx, &conn_handle, 2); indx += 2; attr_handle = htobs(attr_handle); memcpy(buffer + indx, &attr_handle, 2); indx += 2; buffer[indx] = write_status; indx += 1; buffer[indx] = err_code; indx += 1; buffer[indx] = att_val_len; indx += 1; memcpy(buffer + indx, &att_val, att_val_len); indx += att_val_len; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GATT_WRITE_RESPONSE; rq.cparam = (void *)buffer; rq.clen = indx; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return status; } return 0; }
tBleStatus aci_gatt_set_desc_value(uint16_t servHandle, uint16_t charHandle, uint16_t charDescHandle, uint16_t charDescValOffset, uint8_t charDescValueLen, const uint8_t *charDescValue) { struct hci_request rq; uint8_t status; uint8_t buffer[HCI_MAX_PAYLOAD_SIZE]; uint8_t indx = 0; if ((charDescValueLen+9) > HCI_MAX_PAYLOAD_SIZE) return BLE_STATUS_INVALID_PARAMS; servHandle = htobs(servHandle); Osal_MemCpy(buffer + indx, &servHandle, 2); indx += 2; charHandle = htobs(charHandle); Osal_MemCpy(buffer + indx, &charHandle, 2); indx += 2; charDescHandle = htobs(charDescHandle); Osal_MemCpy(buffer + indx, &charDescHandle, 2); indx += 2; Osal_MemCpy(buffer + indx, &charDescValOffset, 2); indx += 2; buffer[indx] = charDescValueLen; indx++; Osal_MemCpy(buffer + indx, charDescValue, charDescValueLen); indx += charDescValueLen; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GATT_SET_DESC_VAL; rq.cparam = (void *)buffer; rq.clen = indx; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; return status; }
tBleStatus aci_gatt_disc_charac_by_uuid(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint8_t charUuidType, const uint8_t* charUuid) { struct hci_request rq; uint8_t status; uint8_t buffer[23]; uint8_t uuid_len; uint8_t indx = 0; conn_handle = htobs(conn_handle); Osal_MemCpy(buffer + indx, &conn_handle, 2); indx += 2; start_handle = htobs(start_handle); Osal_MemCpy(buffer + indx, &start_handle, 2); indx += 2; end_handle = htobs(end_handle); Osal_MemCpy(buffer + indx, &end_handle, 2); indx += 2; buffer[indx] = charUuidType; indx++; if(charUuidType == 0x01){ uuid_len = 2; } else { uuid_len = 16; } Osal_MemCpy(buffer + indx, charUuid, uuid_len); indx += uuid_len; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GATT_DISC_CHARAC_BY_UUID; rq.cparam = (void *)buffer; rq.clen = indx; rq.event = EVT_CMD_STATUS; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; return status; }
tBleStatus aci_gatt_add_serv(uint8_t service_uuid_type, const uint8_t* service_uuid, uint8_t service_type, uint8_t max_attr_records, uint16_t *serviceHandle) { struct hci_request rq; gatt_add_serv_rp resp; uint8_t buffer[19]; uint8_t uuid_len; uint8_t indx = 0; buffer[indx] = service_uuid_type; indx++; if(service_uuid_type == UUID_TYPE_16){ uuid_len = 2; } else { uuid_len = 16; } Osal_MemCpy(buffer + indx, service_uuid, uuid_len); indx += uuid_len; buffer[indx] = service_type; indx++; buffer[indx] = max_attr_records; indx++; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GATT_ADD_SERV; rq.cparam = (void *)buffer; rq.clen = indx; rq.rparam = &resp; rq.rlen = GATT_ADD_SERV_RP_SIZE; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; if (resp.status) { return resp.status; } *serviceHandle = btohs(resp.handle); return 0; }
tBleStatus aci_gatt_add_serv(tHalUint8 service_uuid_type, const tHalUint8* service_uuid, tHalUint8 service_type, tHalUint8 max_attr_records, tHalUint16 *serviceHandle) { struct hci_request rq; gatt_add_serv_rp resp; uint8_t buffer[19]; uint8_t uuid_len; uint8_t indx = 0; buffer[indx] = service_uuid_type; indx++; if(service_uuid_type == 0x01){ uuid_len = 2; } else { uuid_len = 16; } memcpy(buffer + indx, service_uuid, uuid_len); indx += uuid_len; buffer[indx] = service_type; indx++; buffer[indx] = max_attr_records; indx++; memset(&resp, 0, sizeof(resp)); memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GATT_ADD_SERV; rq.cparam = (void *)buffer; rq.clen = indx; rq.rparam = &resp; rq.rlen = GATT_ADD_SERV_RP_SIZE; if (hci_send_req(&rq) < 0) return -1; if (resp.status) { return resp.status; } *serviceHandle = btohs(resp.handle); return 0; }
tBleStatus aci_gap_allow_rebond_IDB04A1(void) { struct hci_request rq; uint8_t status; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GAP_ALLOW_REBOND_DB; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; return status; }
tBleStatus aci_gatt_init(void) { struct hci_request rq; uint8_t status; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GATT_INIT; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; return status; }
tBleStatus aci_gap_set_non_discoverable(void) { struct hci_request rq; uint8_t status; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GAP_SET_NON_DISCOVERABLE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; return status; }
tBleStatus aci_reset_blue_flag(void) { struct hci_request rq; tHalUint8 status; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_UPDATER_RESET_BLUE_FLAG; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; return status; }
tBleStatus aci_updater_reboot(void) { struct hci_request rq; tHalUint8 status; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_UPDATER_REBOOT; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; return status; }
tBleStatus aci_hal_device_standby(void) { struct hci_request rq; uint8_t status; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_HAL_DEVICE_STANDBY; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; return status; }
tBleStatus aci_gap_clear_security_database(void) { struct hci_request rq; uint8_t status; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GAP_CLEAR_SECURITY_DB; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; return status; }
tBleStatus aci_gap_set_non_discoverable(void) { struct hci_request rq; tHalUint8 status; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GAP_SET_NON_DISCOVERABLE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; return status; }
tBleStatus aci_gap_configure_whitelist(void) { struct hci_request rq; uint8_t status; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GAP_CONFIGURE_WHITELIST; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; return status; }
int hci_reset() { struct hci_request rq; uint8_t status; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_RESET; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; return status; }
int hci_le_clear_white_list() { struct hci_request rq; uint8_t status; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_CLEAR_WHITE_LIST; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq, FALSE) < 0){ return BLE_STATUS_TIMEOUT; } return status; }
static int l2cap_bluez_set_flush_timeout(int channel, int timeout_ms) { int result = 0, dd; struct hci_request rq = { 0 }; write_link_supervision_timeout_cp cmd_param; write_link_supervision_timeout_rp cmd_response; if ((dd = hci_open_dev(channels.channels[channel].devid)) < 0) { perror("hci_open_dev"); return -1; } // build a command packet to send to the bluetooth microcontroller cmd_param.handle = channels.channels[channel].handle; cmd_param.timeout = htobs(timeout_ms/BT_SLOT); rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_WRITE_AUTOMATIC_FLUSH_TIMEOUT; rq.cparam = &cmd_param; rq.clen = sizeof(cmd_param); rq.rparam = &cmd_response; rq.rlen = sizeof(cmd_response); rq.event = EVT_CMD_COMPLETE; // send the command and wait for the response if( hci_send_req( dd, &rq, 0 ) < 0) { perror("hci_send_req"); result = -1; } else if( cmd_response.status ) { errno = bt_error(cmd_response.status); perror("failed to set flush timeout"); result = -1; } hci_close_dev(dd); return result; }
tBleStatus aci_gap_terminate_gap_procedure(uint8_t procedure_code) { struct hci_request rq; uint8_t status; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GAP_TERMINATE_GAP_PROCEDURE; rq.cparam = &procedure_code; rq.clen = 1; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq, FALSE) < 0) return BLE_STATUS_TIMEOUT; return status; }
tBleStatus aci_gatt_init() { struct hci_request rq; tHalUint8 status; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_VENDOR_CMD; rq.ocf = OCF_GATT_INIT; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return status; } return 0; }