aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/direct_bt/HCIComm.hpp85
-rw-r--r--src/direct_bt/HCIComm.cpp227
2 files changed, 244 insertions, 68 deletions
diff --git a/api/direct_bt/HCIComm.hpp b/api/direct_bt/HCIComm.hpp
index c9474565..1b34b670 100644
--- a/api/direct_bt/HCIComm.hpp
+++ b/api/direct_bt/HCIComm.hpp
@@ -53,6 +53,84 @@ namespace direct_bt {
LE_Advertising_Report = 0x3E
};
+ /**
+ * BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes
+ * <p>
+ * BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 2 Error code descriptions
+ * </p>
+ */
+ enum class HCIErrorCode : uint8_t {
+ SUCCESS = 0x00,
+ UNKNOWN_HCI_COMMAND = 0x01,
+ UNKNOWN_CONNECTION_IDENTIFIER = 0x02,
+ HARDWARE_FAILURE = 0x03,
+ PAGE_TIMEOUT = 0x04,
+ AUTHENTICATION_FAILURE = 0x05,
+ PIN_OR_KEY_MISSING = 0x06,
+ MEMORY_CAPACITY_EXCEEDED = 0x07,
+ CONNECTION_TIMEOUT = 0x08,
+ CONNECTION_LIMIT_EXCEEDED = 0x09,
+ SYNC_DEVICE_CONNECTION_LIMIT_EXCEEDED = 0x0a,
+ CONNECTION_ALREADY_EXISTS = 0x0b,
+ COMMAND_DISALLOWED = 0x0c,
+ CONNECTION_REJECTED_LIMITED_RESOURCES = 0x0d,
+ CONNECTION_REJECTED_SECURITY = 0x0e,
+ CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR = 0x0f,
+ CONNECTION_ACCEPT_TIMEOUT_EXCEEDED = 0x10,
+ UNSUPPORTED_FEATURE_OR_PARAM_VALUE = 0x11,
+ INVALID_HCI_COMMAND_PARAMETERS = 0x12,
+ REMOTE_USER_TERMINATED_CONNECTION = 0x13,
+ REMOTE_DEVICE_TERMINATED_CONNECTION_LOW_RESOURCES = 0x14,
+ REMOTE_DEVICE_TERMINATED_CONNECTION_POWER_OFF = 0x15,
+ CONNECTION_TERMINATED_BY_LOCAL_HOST = 0x16,
+ REPEATED_ATTEMPTS = 0x17,
+ PAIRING_NOT_ALLOWED = 0x18,
+ UNKNOWN_LMP_PDU = 0x19,
+ UNSUPPORTED_REMOTE_OR_LMP_FEATURE = 0x1a,
+ SCO_OFFSET_REJECTED = 0x1b,
+ SCO_INTERVAL_REJECTED = 0x1c,
+ SCO_AIR_MODE_REJECTED = 0x1d,
+ INVALID_LMP_OR_LL_PARAMETERS = 0x1e,
+ UNSPECIFIED_ERROR = 0x1f,
+ UNSUPPORTED_LMP_OR_LL_PARAMETER_VALUE = 0x20,
+ ROLE_CHANGE_NOT_ALLOWED = 0x21,
+ LMP_OR_LL_RESPONSE_TIMEOUT = 0x22,
+ LMP_OR_LL_COLLISION = 0x23,
+ LMP_PDU_NOT_ALLOWED = 0x24,
+ ENCRYPTION_MODE_NOT_ACCEPTED = 0x25,
+ LINK_KEY_CANNOT_BE_CHANGED = 0x26,
+ REQUESTED_QOS_NOT_SUPPORTED = 0x27,
+ INSTANT_PASSED = 0x28,
+ PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED = 0x29,
+ DIFFERENT_TRANSACTION_COLLISION = 0x2a,
+ QOS_UNACCEPTABLE_PARAMETER = 0x2c,
+ QOS_REJECTED = 0x2d,
+ CHANNEL_ASSESSMENT_NOT_SUPPORTED = 0x2e,
+ INSUFFICIENT_SECURITY = 0x2f,
+ PARAMETER_OUT_OF_RANGE = 0x30,
+ ROLE_SWITCH_PENDING = 0x32,
+ RESERVED_SLOT_VIOLATION = 0x34,
+ ROLE_SWITCH_FAILED = 0x35,
+ EIR_TOO_LARGE = 0x36,
+ SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST = 0x37,
+ HOST_BUSY_PAIRING = 0x38,
+ CONNECTION_REJECTED_NO_SUITABLE_CHANNEL = 0x39,
+ CONTROLLER_BUSY = 0x3a,
+ UNACCEPTABLE_CONNECTION_PARAM = 0x3b,
+ ADVERTISING_TIMEOUT = 0x3c,
+ CONNECTION_TERMINATED_MIC_FAILURE = 0x3d,
+ CONNECTION_EST_FAILED_OR_SYNC_TIMETOUT = 0x3e,
+ MAX_CONNECTION_FAILED = 0x3f,
+ COARSE_CLOCK_ADJ_REJECTED = 0x40,
+ TYPE0_SUBMAP_NOT_DEFINED = 0x41,
+ UNKNOWN_ADVERTISING_IDENTIFIER = 0x42,
+ LIMIT_REACHED = 0x43,
+ OPERATION_CANCELLED_BY_HOST = 0x44,
+ PACKET_TOO_LONG = 0x45,
+ INTERNAL_FAILURE = 0xff
+ };
+ std::string getHCIErrorCodeString(const HCIErrorCode ec);
+
class HCIComm {
private:
static int hci_open_dev(const uint16_t dev_id, const uint16_t channel);
@@ -66,8 +144,8 @@ namespace direct_bt {
bool le_scanning;
bool send_cmd(const uint16_t opcode, const void *command, const uint8_t command_len);
- bool send_req(const uint16_t opcode, const void *command, const uint8_t command_len,
- const uint16_t exp_event, void *response, const uint8_t response_len);
+ HCIErrorCode send_req(const uint16_t opcode, const void *command, const uint8_t command_len,
+ const uint16_t exp_event, void *response, const uint8_t response_len);
bool le_set_scan_enable(const uint8_t enable, const uint8_t filter_dup);
bool le_set_scan_parameters(const uint8_t type, const uint16_t interval,
@@ -124,6 +202,9 @@ namespace direct_bt {
/**
* Establish a connection to the given LE peer.
* <p>
+ * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.12 LE Create Connection command
+ * </p>
+ * <p>
* Even if not utilizing a HCI channel, it has been observed that maintaining such
* enhanced performance on subsequent communication, i.e. GATT over L2CAP.
* </p>
diff --git a/src/direct_bt/HCIComm.cpp b/src/direct_bt/HCIComm.cpp
index 3344830f..e765f8fa 100644
--- a/src/direct_bt/HCIComm.cpp
+++ b/src/direct_bt/HCIComm.cpp
@@ -50,6 +50,86 @@ extern "C" {
namespace direct_bt {
+#define HCI_ERROR_CODE(X) \
+ X(SUCCESS) \
+ X(UNKNOWN_HCI_COMMAND) \
+ X(UNKNOWN_CONNECTION_IDENTIFIER) \
+ X(HARDWARE_FAILURE) \
+ X(PAGE_TIMEOUT) \
+ X(AUTHENTICATION_FAILURE) \
+ X(PIN_OR_KEY_MISSING) \
+ X(MEMORY_CAPACITY_EXCEEDED) \
+ X(CONNECTION_TIMEOUT) \
+ X(CONNECTION_LIMIT_EXCEEDED) \
+ X(SYNC_DEVICE_CONNECTION_LIMIT_EXCEEDED) \
+ X(CONNECTION_ALREADY_EXISTS) \
+ X(COMMAND_DISALLOWED) \
+ X(CONNECTION_REJECTED_LIMITED_RESOURCES) \
+ X(CONNECTION_REJECTED_SECURITY) \
+ X(CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR) \
+ X(CONNECTION_ACCEPT_TIMEOUT_EXCEEDED) \
+ X(UNSUPPORTED_FEATURE_OR_PARAM_VALUE) \
+ X(INVALID_HCI_COMMAND_PARAMETERS) \
+ X(REMOTE_USER_TERMINATED_CONNECTION) \
+ X(REMOTE_DEVICE_TERMINATED_CONNECTION_LOW_RESOURCES) \
+ X(REMOTE_DEVICE_TERMINATED_CONNECTION_POWER_OFF) \
+ X(CONNECTION_TERMINATED_BY_LOCAL_HOST) \
+ X(REPEATED_ATTEMPTS) \
+ X(PAIRING_NOT_ALLOWED) \
+ X(UNKNOWN_LMP_PDU) \
+ X(UNSUPPORTED_REMOTE_OR_LMP_FEATURE) \
+ X(SCO_OFFSET_REJECTED) \
+ X(SCO_INTERVAL_REJECTED) \
+ X(SCO_AIR_MODE_REJECTED) \
+ X(INVALID_LMP_OR_LL_PARAMETERS) \
+ X(UNSPECIFIED_ERROR) \
+ X(UNSUPPORTED_LMP_OR_LL_PARAMETER_VALUE) \
+ X(ROLE_CHANGE_NOT_ALLOWED) \
+ X(LMP_OR_LL_RESPONSE_TIMEOUT) \
+ X(LMP_OR_LL_COLLISION) \
+ X(LMP_PDU_NOT_ALLOWED) \
+ X(ENCRYPTION_MODE_NOT_ACCEPTED) \
+ X(LINK_KEY_CANNOT_BE_CHANGED) \
+ X(REQUESTED_QOS_NOT_SUPPORTED) \
+ X(INSTANT_PASSED) \
+ X(PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED) \
+ X(DIFFERENT_TRANSACTION_COLLISION) \
+ X(QOS_UNACCEPTABLE_PARAMETER) \
+ X(QOS_REJECTED) \
+ X(CHANNEL_ASSESSMENT_NOT_SUPPORTED) \
+ X(INSUFFICIENT_SECURITY) \
+ X(PARAMETER_OUT_OF_RANGE) \
+ X(ROLE_SWITCH_PENDING) \
+ X(RESERVED_SLOT_VIOLATION) \
+ X(ROLE_SWITCH_FAILED) \
+ X(EIR_TOO_LARGE) \
+ X(SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST) \
+ X(HOST_BUSY_PAIRING) \
+ X(CONNECTION_REJECTED_NO_SUITABLE_CHANNEL) \
+ X(CONTROLLER_BUSY) \
+ X(UNACCEPTABLE_CONNECTION_PARAM) \
+ X(ADVERTISING_TIMEOUT) \
+ X(CONNECTION_TERMINATED_MIC_FAILURE) \
+ X(CONNECTION_EST_FAILED_OR_SYNC_TIMETOUT) \
+ X(MAX_CONNECTION_FAILED) \
+ X(COARSE_CLOCK_ADJ_REJECTED) \
+ X(TYPE0_SUBMAP_NOT_DEFINED) \
+ X(UNKNOWN_ADVERTISING_IDENTIFIER) \
+ X(LIMIT_REACHED) \
+ X(OPERATION_CANCELLED_BY_HOST) \
+ X(PACKET_TOO_LONG) \
+ X(INTERNAL_FAILURE)
+
+#define HCI_ERROR_CODE_CASE_TO_STRING(V) case HCIErrorCode::V: return #V;
+
+std::string getHCIErrorCodeString(const HCIErrorCode ec) {
+ switch(ec) {
+ HCI_ERROR_CODE(HCI_ERROR_CODE_CASE_TO_STRING)
+ default: ; // fall through intended
+ }
+ return "Unknown HCI error code";
+}
+
int HCIComm::hci_open_dev(const uint16_t dev_id, const uint16_t channel)
{
sockaddr_hci a;
@@ -230,13 +310,13 @@ bool HCIComm::send_cmd(const uint16_t opcode, const void *command, const uint8_t
#define _HCI_PKT_TRY_COUNT 10
-bool HCIComm::send_req(const uint16_t opcode, const void *command, const uint8_t command_len,
- const uint16_t exp_event, void *response, const uint8_t response_len)
+HCIErrorCode HCIComm::send_req(const uint16_t opcode, const void *command, const uint8_t command_len,
+ const uint16_t exp_event, void *response, const uint8_t response_len)
{
const std::lock_guard<std::recursive_mutex> lock(mtx); // RAII-style acquire and relinquish via destructor
if( 0 > _dd ) {
ERR_PRINT("hci_send_req: device not open");
- return false;
+ return HCIErrorCode::INTERNAL_FAILURE;
}
uint8_t buf[HCI_MAX_EVENT_SIZE];
const uint16_t opcode_le16 = cpu_to_le(opcode);
@@ -249,7 +329,7 @@ bool HCIComm::send_req(const uint16_t opcode, const void *command, const uint8_t
olen = sizeof(of);
if (getsockopt(_dd, SOL_HCI, HCI_FILTER, &of, &olen) < 0) {
ERR_PRINT("hci_send_req");
- return false;
+ return HCIErrorCode::INTERNAL_FAILURE;
}
filter_clear(&nf);
@@ -263,10 +343,11 @@ bool HCIComm::send_req(const uint16_t opcode, const void *command, const uint8_t
filter_set_opcode(opcode_le16, &nf);
if (setsockopt(_dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) {
ERR_PRINT("hci_send_req");
- return false;
+ return HCIErrorCode::INTERNAL_FAILURE;
}
int _timeoutMS = timeoutMS;
+ HCIErrorCode res = HCIErrorCode::INTERNAL_FAILURE;
if ( !send_cmd(opcode, command, command_len) ) {
ERR_PRINT("hci_send_req");
@@ -330,18 +411,23 @@ bool HCIComm::send_req(const uint16_t opcode, const void *command, const uint8_t
switch (hdr->evt) {
case HCI_EV_CMD_STATUS: {
const hci_ev_cmd_status *cs = static_cast<const hci_ev_cmd_status *>(static_cast<const void *>( ptr ));
+ const HCIErrorCode status = static_cast<HCIErrorCode>(cs->status);
- DBG_PRINT("hci_send_req: HCI_EV_CMD_STATUS: opcode 0x%X, exp_event 0x%X, status 0x%2.2X, rlen %d/%d",
- cs->opcode, exp_event, cs->status, response_len, len);
+ DBG_PRINT("hci_send_req: HCI_EV_CMD_STATUS: opcode 0x%X, exp_event 0x%X, status 0x%2.2X (%s), rlen %d/%d",
+ cs->opcode, exp_event,
+ cs->status, getHCIErrorCodeString(status).c_str(),
+ response_len, len);
if (cs->opcode != opcode_le16) {
continue;
}
if (exp_event != HCI_EV_CMD_STATUS) {
- if (cs->status) {
+ if ( HCIErrorCode::SUCCESS != status ) {
errno = EIO;
- ERR_PRINT("hci_send_req: event exp 0x%X != has 0x%X, error status 0x%2.2X", exp_event, hdr->evt, cs->status);
+ ERR_PRINT("hci_send_req: event exp 0x%X != has 0x%X, error status 0x%2.2X (%s)", exp_event,
+ hdr->evt, cs->status, getHCIErrorCodeString(status).c_str());
+ res = status;
goto failed;
}
break;
@@ -439,11 +525,11 @@ failed:
err = errno;
setsockopt(_dd, SOL_HCI, HCI_FILTER, &of, sizeof(of));
errno = err;
- return false;
+ return res;
done:
setsockopt(_dd, SOL_HCI, HCI_FILTER, &of, sizeof(of));
- return true;
+ return HCIErrorCode::SUCCESS;
}
bool HCIComm::disconnect(const uint16_t le_conn_handle, const uint8_t reason)
@@ -462,18 +548,20 @@ bool HCIComm::disconnect(const uint16_t le_conn_handle, const uint8_t reason)
cp.handle = le_conn_handle;
cp.reason = reason;
- if( !send_req( hci_opcode_pack(OGF_LINK_CTL, HCI_OP_DISCONNECT), &cp, sizeof(cp),
- HCI_EV_DISCONN_COMPLETE, &rp, sizeof(rp) ) )
- {
- DBG_PRINT("hci_disconnect: errno %d %s", errno, strerror(errno));
- return false;
- }
-
- if (rp.status) {
- errno = EIO;
- DBG_PRINT("hci_disconnect: error status 0x%2.2X, errno %d %s", rp.status, errno, strerror(errno));
- return false;
- }
+ HCIErrorCode res = send_req( hci_opcode_pack(OGF_LINK_CTL, HCI_OP_DISCONNECT), &cp, sizeof(cp),
+ HCI_EV_DISCONN_COMPLETE, &rp, sizeof(rp) );
+ if( HCIErrorCode::SUCCESS != res ) {
+ ERR_PRINT("hci_disconnect: 0x%2.2X (%s), errno %d %s",
+ static_cast<uint8_t>(res), getHCIErrorCodeString(res).c_str(), errno, strerror(errno));
+ return false;
+ }
+ HCIErrorCode status = static_cast<HCIErrorCode>(rp.status);
+ if( HCIErrorCode::SUCCESS != status ) {
+ errno = EIO;
+ ERR_PRINT("hci_disconnect: error status 0x%2.2X (%s), errno %d %s",
+ rp.status, getHCIErrorCodeString(status).c_str(), errno, strerror(errno));
+ return false;
+ }
return true;
}
@@ -484,24 +572,25 @@ bool HCIComm::le_set_scan_enable(const uint8_t enable, const uint8_t filter_dup)
return false;
}
hci_cp_le_set_scan_enable cp;
- uint8_t status;
+ HCIErrorCode status;
bzero(&cp, sizeof(cp));
cp.enable = enable;
cp.filter_dup = filter_dup;
- if( !send_req( hci_opcode_pack(OGF_LE_CTL, HCI_OP_LE_SET_SCAN_ENABLE), &cp, sizeof(cp),
- 0, &status, sizeof(status) ) )
- {
- ERR_PRINT("hci_le_set_scan_enable(%d)", enable);
+ HCIErrorCode res = send_req( hci_opcode_pack(OGF_LE_CTL, HCI_OP_LE_SET_SCAN_ENABLE), &cp, sizeof(cp),
+ 0, &status, sizeof(status) );
+ if( HCIErrorCode::SUCCESS != res ) {
+ ERR_PRINT("hci_le_set_scan_enable(%d): 0x%2.2X (%s), errno %d %s",
+ enable, static_cast<uint8_t>(res), getHCIErrorCodeString(res).c_str(), errno, strerror(errno));
+ return false;
+ }
+ if( HCIErrorCode::SUCCESS != status ) {
+ errno = EIO;
+ ERR_PRINT("hci_le_set_scan_enable(%d): error status 0x%2.2X (%s), errno %d %s",
+ enable, static_cast<uint8_t>(status), getHCIErrorCodeString(status).c_str(), errno, strerror(errno));
return false;
}
-
- if (status) {
- errno = EIO;
- ERR_PRINT("hci_le_set_scan_enable(%d): error status 0x%2.2X", enable, status);
- return false;
- }
return true;
}
@@ -515,7 +604,7 @@ bool HCIComm::le_set_scan_parameters(const uint8_t type, const uint16_t interval
return false;
}
hci_cp_le_set_scan_param cp;
- uint8_t status;
+ HCIErrorCode status;
bzero(&cp, sizeof(cp));
cp.type = type;
@@ -524,19 +613,19 @@ bool HCIComm::le_set_scan_parameters(const uint8_t type, const uint16_t interval
cp.own_address_type = own_type;
cp.filter_policy = filter;
- if( !send_req( hci_opcode_pack(OGF_LE_CTL, HCI_OP_LE_SET_SCAN_PARAM), &cp, sizeof(cp),
- 0, &status, sizeof(status) ) )
- {
- ERR_PRINT("hci_le_set_scan_parameters");
+ HCIErrorCode res = send_req( hci_opcode_pack(OGF_LE_CTL, HCI_OP_LE_SET_SCAN_PARAM), &cp, sizeof(cp),
+ 0, &status, sizeof(status) );
+ if( HCIErrorCode::SUCCESS != res ) {
+ ERR_PRINT("hci_le_set_scan_parameters: 0x%2.2X (%s), errno %d %s",
+ static_cast<uint8_t>(res), getHCIErrorCodeString(res).c_str(), errno, strerror(errno));
+ return false;
+ }
+ if( HCIErrorCode::SUCCESS != status ) {
+ errno = EIO;
+ ERR_PRINT("hci_le_set_scan_parameters: error status 0x%2.2X (%s), errno %d %s",
+ static_cast<uint8_t>(status), getHCIErrorCodeString(status).c_str(), errno, strerror(errno));
return false;
}
-
- if (status) {
- errno = EIO;
- ERR_PRINT("hci_le_set_scan_parameters: error status 0x%2.2X", status);
- return false;
- }
-
return true;
}
@@ -596,6 +685,8 @@ uint16_t HCIComm::le_create_conn(const EUI48 &peer_bdaddr,
const uint16_t min_interval, const uint16_t max_interval,
const uint16_t latency, const uint16_t supervision_timeout)
{
+
+ /** BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.12 LE Create Connection command */
const std::lock_guard<std::recursive_mutex> lock(mtx); // RAII-style acquire and relinquish via destructor
if( 0 > _dd ) {
ERR_PRINT("hci_le_create_conn: device not open");
@@ -604,9 +695,9 @@ uint16_t HCIComm::le_create_conn(const EUI48 &peer_bdaddr,
hci_cp_le_create_conn cp;
hci_ev_le_conn_complete rp;
- const uint16_t min_ce_length = 0x0000; // 0x0001 ??
- const uint16_t max_ce_length = 0x0000; // 0x0001 ??
- const uint8_t initiator_filter = 0x00;
+ const uint16_t min_ce_length = 0x0001; // 0x0001 ??
+ const uint16_t max_ce_length = 0x0001; // 0x0001 ??
+ const uint8_t initiator_filter = 0x00; // whitelist not used but peer_bdaddr*
bzero((void*)&cp, sizeof(cp));
@@ -623,18 +714,20 @@ uint16_t HCIComm::le_create_conn(const EUI48 &peer_bdaddr,
cp.min_ce_len = cpu_to_le(min_ce_length);
cp.max_ce_len = cpu_to_le(max_ce_length);
- if( !send_req( hci_opcode_pack(OGF_LE_CTL, HCI_OP_LE_CREATE_CONN), &cp, sizeof(cp),
- HCI_EV_LE_CONN_COMPLETE, &rp, sizeof(rp) ) )
- {
- ERR_PRINT("hci_le_create_conn");
+ HCIErrorCode res = send_req( hci_opcode_pack(OGF_LE_CTL, HCI_OP_LE_CREATE_CONN), &cp, sizeof(cp),
+ HCI_EV_LE_CONN_COMPLETE, &rp, sizeof(rp) );
+ if( HCIErrorCode::SUCCESS != res ) {
+ ERR_PRINT("hci_le_create_conn: error status 0x%2.2X (%s), errno %d %s",
+ static_cast<uint8_t>(res), getHCIErrorCodeString(res).c_str(), errno, strerror(errno));
+ return 0;
+ }
+ HCIErrorCode status = static_cast<HCIErrorCode>(rp.status);
+ if( HCIErrorCode::SUCCESS != status ) {
+ errno = EIO;
+ ERR_PRINT("hci_le_create_conn: error status 0x%2.2X (%s), errno %d %s",
+ rp.status, getHCIErrorCodeString(status).c_str(), errno, strerror(errno));
return 0;
}
-
- if (rp.status) {
- errno = EIO;
- ERR_PRINT("hci_le_create_conn: error status 0x%2.2X", rp.status);
- return 0;
- }
return rp.handle;
}
@@ -657,16 +750,18 @@ uint16_t HCIComm::create_conn(const EUI48 &bdaddr, const uint16_t pkt_type,
cp.clock_offset = cpu_to_le(clock_offset);
cp.role_switch = role_switch;
- if( !send_req( hci_opcode_pack(OGF_LINK_CTL, HCI_OP_CREATE_CONN), &cp, sizeof(cp),
- HCI_EV_CONN_COMPLETE, &rp, sizeof(rp) ) )
- {
- ERR_PRINT("hci_create_conn");
+ HCIErrorCode res = send_req( hci_opcode_pack(OGF_LINK_CTL, HCI_OP_CREATE_CONN), &cp, sizeof(cp),
+ HCI_EV_CONN_COMPLETE, &rp, sizeof(rp) );
+ if( HCIErrorCode::SUCCESS != res ) {
+ ERR_PRINT("hci_create_conn: error status 0x%2.2X (%s), errno %d %s",
+ static_cast<uint8_t>(res), getHCIErrorCodeString(res).c_str(), errno, strerror(errno));
return 0;
}
-
- if (rp.status) {
+ HCIErrorCode status = static_cast<HCIErrorCode>(rp.status);
+ if( HCIErrorCode::SUCCESS != status ) {
errno = EIO;
- ERR_PRINT("hci_create_conn: error status 0x%2.2X", rp.status);
+ ERR_PRINT("hci_create_conn: error status 0x%2.2X (%s), errno %d %s",
+ rp.status, getHCIErrorCodeString(status).c_str(), errno, strerror(errno));
return 0;
}
return rp.handle;