aboutsummaryrefslogtreecommitdiffstats
path: root/src/direct_bt/HCIComm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/direct_bt/HCIComm.cpp')
-rw-r--r--src/direct_bt/HCIComm.cpp581
1 files changed, 0 insertions, 581 deletions
diff --git a/src/direct_bt/HCIComm.cpp b/src/direct_bt/HCIComm.cpp
index d1e8b2d2..aedbad01 100644
--- a/src/direct_bt/HCIComm.cpp
+++ b/src/direct_bt/HCIComm.cpp
@@ -50,87 +50,6 @@ 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) \
- X(UNKNOWN)
-
-#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;
@@ -263,504 +182,4 @@ errout:
return -1;
}
-bool HCIComm::send_cmd(const uint16_t opcode, const void *command, const uint8_t command_len)
-{
- if( 0 > _dd ) {
- ERR_PRINT("hci_send_cmd: device not open");
- return false;
- }
- const uint8_t type = HCI_COMMAND_PKT;
- hci_command_hdr hc;
- struct iovec iv[3];
- int ivn;
- int bw=0;
-
- hc.opcode = cpu_to_le(opcode);
- hc.plen= command_len;
-
- iv[0].iov_base = (void*)&type;
- iv[0].iov_len = 1;
- iv[1].iov_base = (void*)&hc;
- iv[1].iov_len = HCI_COMMAND_HDR_SIZE;
- ivn = 2;
-
- if (command_len) {
- iv[2].iov_base = (void*)command;
- iv[2].iov_len = command_len;
- ivn = 3;
- }
-
-#ifdef VERBOSE_ON
- {
- fprintf(stderr, "hci_send_cmd: type 0x%2.2X, opcode 0x%X, plen %d\n", type, hc.opcode, command_len);
- std::string paramstr = command_len > 0 ? bytesHexString((uint8_t*)command, 0, command_len, false /* lsbFirst */, true /* leading0X */) : "";
- fprintf(stderr, "hci_send_cmd: param: %s\n", paramstr.c_str());
- }
-#endif
-
- while ( ( bw = ::writev(_dd, iv, ivn) ) < 0 ) {
- ERR_PRINT("hci_send_cmd: writev res %d", bw);
- if (errno == EAGAIN || errno == EINTR) {
- continue;
- }
- return false;
- }
- DBG_PRINT("hci_send_cmd: writev: %d", bw);
- return true;
-}
-
-#define _HCI_PKT_TRY_COUNT 10
-
-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 HCIErrorCode::INTERNAL_FAILURE;
- }
- uint8_t buf[HCI_MAX_EVENT_SIZE];
- const uint16_t opcode_le16 = cpu_to_le(opcode);
- hci_ufilter nf, of;
- socklen_t olen;
- int err, tryCount=0;
-
- DBG_PRINT("hci_send_req: opcode 0x%X ", opcode_le16);
-
- olen = sizeof(of);
- if (getsockopt(_dd, SOL_HCI, HCI_FILTER, &of, &olen) < 0) {
- ERR_PRINT("hci_send_req");
- return HCIErrorCode::INTERNAL_FAILURE;
- }
-
- filter_clear(&nf);
- filter_set_ptype(HCI_EVENT_PKT, &nf);
- filter_set_event(HCI_EV_CMD_STATUS, &nf);
- filter_set_event(HCI_EV_CMD_COMPLETE, &nf);
- filter_set_event(HCI_EV_LE_META, &nf);
- filter_set_event(exp_event, &nf);
- filter_set_opcode(opcode_le16, &nf);
- if (setsockopt(_dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) {
- ERR_PRINT("hci_send_req");
- return HCIErrorCode::INTERNAL_FAILURE;
- }
-
- int _timeoutMS = timeoutMS;
- HCIErrorCode res = HCIErrorCode::INTERNAL_FAILURE;
-
- if ( !send_cmd(opcode, command, command_len) ) {
- ERR_PRINT("hci_send_req");
- goto failed;
- }
-
- // Reading up to 10 packets for HCI responses,
- while ( _HCI_PKT_TRY_COUNT > tryCount++ ) {
- if ( _timeoutMS ) {
- struct pollfd p;
- int n;
-
- p.fd = _dd; p.events = POLLIN;
-#if 0
- sigset_t sigmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGALRM);
- struct timespec timeout_ts;
- timeout_ts.tv_sec=0;
- timeout_ts.tv_nsec=(long)_timeoutMS*1000000L;
- while ((n = ppoll(&p, 1, &timeout_ts, &sigmask)) < 0) {
-#else
- while ((n = poll(&p, 1, _timeoutMS)) < 0) {
-#endif
- ERR_PRINT("HCIComm::send_req(dev_id %d, channel %d): poll: res %d", dev_id, channel, n);
- if (errno == EAGAIN || errno == EINTR) {
- continue;
- }
- goto failed;
- }
-
- if (!n) {
- DBG_PRINT("hci_send_req: poll: timeout");
- errno = ETIMEDOUT;
- goto failed;
- }
-
- _timeoutMS -= _timeoutMS/_HCI_PKT_TRY_COUNT; // reduce timeout consecutively
- if ( _timeoutMS < 0 ) {
- _timeoutMS = 0;
- }
- }
-
- int len;
-
- while ((len = ::read(_dd, buf, sizeof(buf))) < 0) {
- ERR_PRINT("HCIComm::send_req(dev_id %d, channel %d): read: res %d", dev_id, channel, len);
- if (errno == EAGAIN || errno == EINTR) {
- continue;
- }
- goto failed;
- }
-
- const hci_event_hdr *hdr = static_cast<hci_event_hdr *>(static_cast<void *>(buf + 1));
- const uint8_t * ptr = buf + (1 + HCI_EVENT_HDR_SIZE);
- len -= (1 + HCI_EVENT_HDR_SIZE);
-
- DBG_PRINT("hci_send_req: read: %d bytes, evt 0x%2.2X", len, hdr->evt);
-
- 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 (%s), rlen %d/%d",
- cs->opcode, exp_event,
- cs->status, getHCIErrorCodeString(status).c_str(),
- response_len, len);
-
- if (cs->opcode != opcode_le16) {
- continue; // next packet
- }
-
- if (exp_event != HCI_EV_CMD_STATUS) {
- if ( HCIErrorCode::SUCCESS != status ) {
- errno = EIO;
- DBG_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;
- }
- continue; // next packet
- }
-
- const int rlen = MIN(len, response_len);
- memcpy(response, ptr, rlen);
- DBG_PRINT("hci_send_req: HCI_EV_CMD_STATUS: copied %d bytes: %s",
- rlen, bytesHexString((uint8_t*)ptr, 0, rlen, false /* lsbFirst */, true /* leading0X */).c_str());
- goto done;
- }
-
- case HCI_EV_CMD_COMPLETE: {
- const hci_ev_cmd_complete *cc = static_cast<const hci_ev_cmd_complete *>(static_cast<const void *>( ptr ));
-
- DBG_PRINT("hci_send_req: HCI_EV_CMD_COMPLETE: opcode 0x%X (equal %d), exp_event 0x%X, r-len %d/%d",
- cc->opcode, (cc->opcode == opcode_le16), exp_event, response_len, len);
-
- if (cc->opcode != opcode_le16) {
- continue; // next packet
- }
-
- ptr += sizeof(hci_ev_cmd_complete);
- len -= sizeof(hci_ev_cmd_complete);
-
- const int rlen = MIN(len, response_len);
- memcpy(response, ptr, rlen);
- DBG_PRINT("hci_send_req: HCI_EV_CMD_COMPLETE: copied %d bytes: %s",
- rlen, bytesHexString((uint8_t*)ptr, 0, rlen, false /* lsbFirst */, true /* leading0X */).c_str());
- goto done;
- }
-
- case HCI_EV_LE_META: {
- const hci_ev_le_meta *me = static_cast<const hci_ev_le_meta *>(static_cast<const void *>( ptr ));
-
- DBG_PRINT("hci_send_req: HCI_EV_LE_META: subevent 0x%X, exp_event 0x%X (equal %d), r-len %d/%d",
- me->subevent, exp_event, (me->subevent == exp_event), response_len, len);
-
- if (me->subevent != exp_event) {
- continue; // next packet
- }
-
- ptr += 1;
- len -= 1;
-
- const int rlen = MIN(len, response_len);
- memcpy(response, ptr, rlen);
- DBG_PRINT("hci_send_req: HCI_EV_LE_META: copied %d bytes: %s",
- rlen, bytesHexString((uint8_t*)ptr, 0, rlen, false /* lsbFirst */, true /* leading0X */).c_str());
- goto done;
- }
-
- default: {
- DBG_PRINT("hci_send_req: DEFAULT: evt 0x%X, exp_event 0x%X (equal %d), r-len %d/%d",
- hdr->evt, exp_event, (hdr->evt == exp_event), response_len, len);
-
- if (hdr->evt != exp_event) {
- continue; // next packet
- }
-
- const int rlen = MIN(len, response_len);
- memcpy(response, ptr, rlen);
- DBG_PRINT("hci_send_req: DEFAULT: copied %d bytes: %s",
- rlen, bytesHexString((uint8_t*)ptr, 0, rlen, false /* lsbFirst */, true /* leading0X */).c_str());
- goto done;
- }
- } // switch event
- } // while packets ...
- errno = ETIMEDOUT;
-
-failed:
- err = errno;
- setsockopt(_dd, SOL_HCI, HCI_FILTER, &of, sizeof(of));
- errno = err;
- return res;
-
-done:
- setsockopt(_dd, SOL_HCI, HCI_FILTER, &of, sizeof(of));
- return HCIErrorCode::SUCCESS;
-}
-
-bool HCIComm::disconnect(const uint16_t le_conn_handle, const HCIErrorCode reason)
-{
- /** BT Core Spec v5.2: Vol 4, Part E HCI: 7.1.6 Disconnect command */
- const std::lock_guard<std::recursive_mutex> lock(mtx); // RAII-style acquire and relinquish via destructor
- DBG_PRINT("hci_disconnect: handle 0x%x, reason 0x%x (%s)",
- le_conn_handle, static_cast<uint8_t>(reason), getHCIErrorCodeString(reason).c_str());
- if( 0 > _dd ) {
- return true;
- }
- if( 0 == le_conn_handle ) {
- return true;
- }
- hci_ev_disconn_complete rp;
- hci_cp_disconnect cp;
-
- bzero(&cp, sizeof(cp));
- cp.handle = le_conn_handle;
- cp.reason = static_cast<uint8_t>(reason);
-
- 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;
-}
-
-bool HCIComm::le_set_scan_enable(const uint8_t enable, const uint8_t filter_dup) {
- const std::lock_guard<std::recursive_mutex> lock(mtx); // RAII-style acquire and relinquish via destructor
- if( 0 > _dd ) {
- ERR_PRINT("hci_le_set_scan_enable(%d): device not open", enable);
- return false;
- }
- hci_cp_le_set_scan_enable cp;
- HCIErrorCode status;
-
- bzero(&cp, sizeof(cp));
- cp.enable = enable;
- cp.filter_dup = filter_dup;
-
- 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;
- }
- return true;
-}
-
-bool HCIComm::le_set_scan_parameters(const uint8_t type, const uint16_t interval,
- const uint16_t window, const uint8_t own_type,
- const uint8_t filter)
-{
- const std::lock_guard<std::recursive_mutex> lock(mtx); // RAII-style acquire and relinquish via destructor
- if( 0 > _dd ) {
- ERR_PRINT("hci_le_set_scan_parameters: device not open");
- return false;
- }
- hci_cp_le_set_scan_param cp;
- HCIErrorCode status;
-
- bzero(&cp, sizeof(cp));
- cp.type = type;
- cp.interval = cpu_to_le(interval);
- cp.window = cpu_to_le(window);
- cp.own_address_type = own_type;
- cp.filter_policy = filter;
-
- 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;
- }
- return true;
-}
-
-void HCIComm::le_disable_scan() {
- const std::lock_guard<std::recursive_mutex> lock(mtx); // RAII-style acquire and relinquish via destructor
- if( 0 > _dd ) {
- return;
- }
- if( !le_scanning ) {
- return;
- }
- const uint8_t filter_dup = 0x01;
-
- if( !le_set_scan_enable(0x00, filter_dup) ) {
- ERR_PRINT("Stop scan failed");
- } else {
- le_scanning = false;
- }
-}
-
-bool HCIComm::le_enable_scan(const HCIAddressType own_type,
- const uint16_t interval, const uint16_t window) {
- const std::lock_guard<std::recursive_mutex> lock(mtx); // RAII-style acquire and relinquish via destructor
- if( 0 > _dd ) {
- DBG_PRINT("hci_le_enable_scan: device not open");
- return false;
- }
- if( le_scanning ) {
- DBG_PRINT("hci_le_enable_scan: device already le-scanning");
- return false;
- }
- const uint8_t scan_type = 0x01;
- // const uint8_t filter_type = 0;
- const uint8_t filter_policy = 0x00;
- const uint8_t filter_dup = 0x01;
-
- bool ok = le_set_scan_parameters(scan_type, interval, window,
- own_type, filter_policy);
- if ( !ok ) {
- ERR_PRINT("Set scan parameters failed");
- return false;
- }
-
- ok = le_set_scan_enable(0x01, filter_dup);
- if ( !ok ) {
- ERR_PRINT("Start scan failed");
- return false;
- }
- le_scanning = true;
- return true;
-}
-
-HCIErrorCode HCIComm::le_create_conn(uint16_t * handle_return, const EUI48 &peer_bdaddr,
- const HCIAddressType peer_mac_type,
- const HCIAddressType own_mac_type,
- const uint16_t le_scan_interval, const uint16_t le_scan_window,
- const uint16_t conn_interval_min, const uint16_t conn_interval_max,
- const uint16_t conn_latency, const uint16_t supervision_timeout)
-{
-
- /** BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.12 LE Create Connection command */
- /** BT Core Spec v5.2: Vol 4, Part E HCI: 7.7.65 LE Meta event: 7.7.65.1 LE Connection Complete event */
- const std::lock_guard<std::recursive_mutex> lock(mtx); // RAII-style acquire and relinquish via destructor
- if( nullptr != handle_return ) {
- *handle_return = 0;
- }
- if( 0 > _dd ) {
- ERR_PRINT("hci_le_create_conn: device not open");
- return HCIErrorCode::INTERNAL_FAILURE;
- }
- hci_cp_le_create_conn cp;
- hci_ev_le_conn_complete rp;
-
- const uint16_t min_ce_length = 0x0000;
- const uint16_t max_ce_length = 0x0000;
- const uint8_t initiator_filter = 0x00; // whitelist not used but peer_bdaddr*
-
- bzero((void*)&cp, sizeof(cp));
- cp.scan_interval = cpu_to_le(le_scan_interval);
- cp.scan_window = cpu_to_le(le_scan_window);
- cp.filter_policy = initiator_filter;
- cp.peer_addr_type = peer_mac_type;
- cp.peer_addr = peer_bdaddr;
- cp.own_address_type = own_mac_type;
- cp.conn_interval_min = cpu_to_le(conn_interval_min);
- cp.conn_interval_max = cpu_to_le(conn_interval_max);
- cp.conn_latency = cpu_to_le(conn_latency);
- cp.supervision_timeout = cpu_to_le(supervision_timeout);
- cp.min_ce_len = cpu_to_le(min_ce_length);
- cp.max_ce_len = cpu_to_le(max_ce_length);
-
- 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::COMMAND_DISALLOWED == res ) {
- WARN_PRINT("hci_le_create_conn: COMMAND_DISALLOWED reply, connect may still be in progress. error status 0x%2.2X (%s), errno %d %s",
- static_cast<uint8_t>(res), getHCIErrorCodeString(res).c_str(), errno, strerror(errno));
- return res;
- }
- 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 res;
- }
- 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 status;
- }
- DBG_PRINT("hci_le_create_conn: Success: handle 0x%x", rp.handle);
- if( nullptr != handle_return ) {
- *handle_return = rp.handle;
- }
- return HCIErrorCode::SUCCESS;
-}
-
-HCIErrorCode HCIComm::create_conn(uint16_t * handle_return, const EUI48 &bdaddr, const uint16_t pkt_type,
- const uint16_t clock_offset, const uint8_t role_switch)
-{
- const std::lock_guard<std::recursive_mutex> lock(mtx); // RAII-style acquire and relinquish via destructor
- if( nullptr != handle_return ) {
- *handle_return = 0;
- }
- if( 0 > _dd ) {
- ERR_PRINT("hci_create_conn: device not open");
- return HCIErrorCode::INTERNAL_FAILURE;
- }
- hci_cp_create_conn cp;
- hci_ev_conn_complete rp;
-
- bzero((void*)&cp, sizeof(cp));
- cp.bdaddr = bdaddr;
- cp.pkt_type = cpu_to_le((uint16_t)(pkt_type & (uint16_t)ACL_PTYPE_MASK)); /* TODO OK excluding SCO_PTYPE_MASK (HCI_HV1 | HCI_HV2 | HCI_HV3) ? */
- cp.pscan_rep_mode = 0x02; /* TODO magic? */
- cp.pscan_mode = 0x00; /* TODO magic? */
- cp.clock_offset = cpu_to_le(clock_offset);
- cp.role_switch = role_switch;
-
- 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 res;
- }
- HCIErrorCode status = static_cast<HCIErrorCode>(rp.status);
- if( HCIErrorCode::SUCCESS != status ) {
- errno = EIO;
- ERR_PRINT("hci_create_conn: error status 0x%2.2X (%s), errno %d %s",
- rp.status, getHCIErrorCodeString(status).c_str(), errno, strerror(errno));
- return status;
- }
- if( nullptr != handle_return ) {
- *handle_return = rp.handle;
- }
- return HCIErrorCode::SUCCESS;
-}
-
} /* namespace direct_bt */