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; }
/** * 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; }