struct ble_hs_conn *
ble_hs_test_util_create_conn(uint16_t handle, uint8_t *addr,
                             ble_gap_conn_fn *cb, void *cb_arg)
{
    struct hci_le_conn_complete evt;
    struct ble_hs_conn *conn;
    int rc;

    ble_hs_test_util_set_ack(
        BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_CREATE_CONN), 0);
    rc = ble_gap_conn_initiate(0, addr, NULL, cb, cb_arg);
    TEST_ASSERT(rc == 0);

    memset(&evt, 0, sizeof evt);
    evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
    evt.status = BLE_ERR_SUCCESS;
    evt.connection_handle = handle;
    evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
    evt.peer_addr_type = BLE_ADDR_TYPE_PUBLIC;
    memcpy(evt.peer_addr, addr, 6);
    evt.conn_itvl = BLE_GAP_INITIAL_CONN_ITVL_MAX;
    evt.conn_latency = BLE_GAP_INITIAL_CONN_LATENCY;
    evt.supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT;
    rc = ble_gap_rx_conn_complete(&evt);
    TEST_ASSERT(rc == 0);

    conn = ble_hs_conn_find(handle);
    TEST_ASSERT_FATAL(conn != NULL);

    ble_hs_test_util_prev_hci_tx_clear();

    return conn;
}
示例#2
0
/**
 * Called when a data packet is received from the controller.  This function
 * consumes the supplied mbuf, regardless of the outcome.
 *
 * @param om                    The incoming data packet, beginning with the
 *                                  HCI ACL data header.
 *
 * @return                      0 on success; nonzero on failure.
 */
int
host_hci_data_rx(struct os_mbuf *om)
{
    struct hci_data_hdr hci_hdr;
    struct ble_hs_conn *conn;
    ble_l2cap_rx_fn *rx_cb;
    struct os_mbuf *rx_buf;
    uint16_t handle;
    int rc;

    rc = host_hci_data_hdr_strip(om, &hci_hdr);
    if (rc == 0) {
        BLE_HS_LOG(DEBUG, "host_hci_data_rx(): handle=%u pb=%x len=%u data=",
                   BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc), 
                   BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc), 
                   hci_hdr.hdh_len);
        ble_hs_misc_log_mbuf(om);

        if (hci_hdr.hdh_len != OS_MBUF_PKTHDR(om)->omp_len) {
            rc = BLE_HS_EBADDATA;
        } else {
            handle = BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc);

            ble_hs_conn_lock();

            conn = ble_hs_conn_find(handle);
            if (conn == NULL) {
                rc = BLE_HS_ENOTCONN;
            } else {
                rc = ble_l2cap_rx(conn, &hci_hdr, om, &rx_cb, &rx_buf);
                om = NULL;
            }

            ble_hs_conn_unlock();
        }
    }

    os_mbuf_free_chain(om);

    if (rc == 0) {
        assert(rx_cb != NULL);
        assert(rx_buf != NULL);
        rc = rx_cb(handle, &rx_buf);
        os_mbuf_free_chain(rx_buf);
    } else if (rc == BLE_HS_EAGAIN) {
        /* More fragments on the way. */
        rc = 0;
    }

    return rc;
}
int
ble_hs_atomic_conn_delete(uint16_t conn_handle)
{
    struct ble_hs_conn *conn;

    ble_hs_lock();
    conn = ble_hs_conn_find(conn_handle);
    if (conn != NULL) {
        ble_hs_conn_remove(conn);
        ble_hs_conn_free(conn);

    }
    ble_hs_unlock();

    return conn != NULL ? 0 : BLE_HS_ENOTCONN;
}
/**
 * Lock restrictions: Caller must lock ble_hs_conn mutex.
 */
int
ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn,
                       struct ble_l2cap_chan **out_chan)
{
    *out_chan = NULL;

    *out_conn = ble_hs_conn_find(conn_handle);
    if (*out_conn == NULL) {
        return BLE_HS_ENOTCONN;
    }

    *out_chan = ble_hs_conn_chan_find(*out_conn, BLE_L2CAP_CID_ATT);
    assert(*out_chan != NULL);

    return 0;
}
static int
ble_os_test_misc_conn_exists(uint16_t conn_handle)
{
    struct ble_hs_conn *conn;

    ble_hs_lock();

    if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
        conn = ble_hs_conn_first();
    } else {
        conn = ble_hs_conn_find(conn_handle);
    }

    ble_hs_unlock();

    return conn != NULL;
}
int
ble_hs_atomic_conn_flags(uint16_t conn_handle, ble_hs_conn_flags_t *out_flags)
{
    struct ble_hs_conn *conn;
    int rc;

    ble_hs_lock();

    conn = ble_hs_conn_find(conn_handle);
    if (conn == NULL) {
        rc = BLE_HS_ENOTCONN;
    } else {
        rc = 0;
        *out_flags = conn->bhc_flags;
    }

    ble_hs_unlock();

    return rc;
}
/**
 * Called when a data packet is received from the controller.  This function
 * consumes the supplied mbuf, regardless of the outcome.
 *
 * @param om                    The incoming data packet, beginning with the
 *                                  HCI ACL data header.
 *
 * @return                      0 on success; nonzero on failure.
 */
int
ble_hs_hci_evt_acl_process(struct os_mbuf *om)
{
    struct hci_data_hdr hci_hdr;
    struct ble_hs_conn *conn;
    ble_l2cap_rx_fn *rx_cb;
    uint16_t conn_handle;
    int reject_cid;
    int rc;

    rc = ble_hs_hci_util_data_hdr_strip(om, &hci_hdr);
    if (rc != 0) {
        goto err;
    }

#if (BLETEST_THROUGHPUT_TEST == 0)
    BLE_HS_LOG(DEBUG, "ble_hs_hci_evt_acl_process(): conn_handle=%u pb=%x "
                      "len=%u data=",
               BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc), 
               BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc), 
               hci_hdr.hdh_len);
    ble_hs_log_mbuf(om);
    BLE_HS_LOG(DEBUG, "\n");
#endif

    if (hci_hdr.hdh_len != OS_MBUF_PKTHDR(om)->omp_len) {
        rc = BLE_HS_EBADDATA;
        goto err;
    }

    conn_handle = BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc);

    ble_hs_lock();

    conn = ble_hs_conn_find(conn_handle);
    if (conn == NULL) {
        /* Peer not connected; quietly discard packet. */
        rc = BLE_HS_ENOTCONN;
        reject_cid = -1;
    } else {
        /* Forward ACL data to L2CAP. */
        rc = ble_l2cap_rx(conn, &hci_hdr, om, &rx_cb, &reject_cid);
        om = NULL;
    }

    ble_hs_unlock();

    switch (rc) {
    case 0:
        /* Final fragment received. */
        BLE_HS_DBG_ASSERT(rx_cb != NULL);
        rc = rx_cb(conn->bhc_rx_chan);
        ble_l2cap_forget_rx(conn, conn->bhc_rx_chan);
        break;

    case BLE_HS_EAGAIN:
        /* More fragments on the way. */
        break;

    default:
        if (reject_cid != -1) {
            ble_l2cap_sig_reject_invalid_cid_tx(conn_handle, 0, 0, reject_cid);
        }
        goto err;
    }

    return 0;

err:
    os_mbuf_free_chain(om);
    return rc;
}