int ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) { #if !NIMBLE_OPT(ATT_CLT_FIND_TYPE) return BLE_HS_ENOTSUP; #endif struct ble_att_find_type_value_hinfo hinfo; int rc; /* Reponse consists of a one-byte opcode (already verified) and a variable * length Handles-Information-List field. Strip the opcode from the * response. */ os_mbuf_adj(*rxom, BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ); /* Parse the Handles-Information-List field, passing each entry to GATT. */ rc = 0; while (OS_MBUF_PKTLEN(*rxom) > 0) { rc = ble_att_clt_parse_find_type_value_hinfo(rxom, &hinfo); if (rc != 0) { break; } ble_gattc_rx_find_type_value_hinfo(conn_handle, &hinfo); os_mbuf_adj(*rxom, BLE_ATT_FIND_TYPE_VALUE_HINFO_BASE_SZ); } /* Notify GATT client that the full response has been parsed. */ ble_gattc_rx_find_type_value_complete(conn_handle, rc); return 0; }
static int nmgr_rsp_fragment(struct nmgr_transport *nt, struct nmgr_hdr *rsp_hdr, struct os_mbuf *rsp, struct os_mbuf *req) { uint16_t mtu; uint16_t rsplen; uint16_t len ; int rc; len = 0; mtu = nt->nt_get_mtu(req); do { len = OS_MBUF_PKTLEN(rsp); if (len >= mtu) { rsplen = mtu; } else { rsplen = len; } rc = nmgr_send_rspfrag(nt, rsp, req, rsplen); if (rc) { goto err; } os_mbuf_adj(rsp, rsplen); } while (OS_MBUF_PKTLEN(rsp)); return MGMT_ERR_EOK; err: return rc; }
int ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) { #if !NIMBLE_OPT(ATT_CLT_PREP_WRITE) return BLE_HS_ENOTSUP; #endif struct ble_att_prep_write_cmd rsp; uint16_t value_len; void *value; int rc; /* Initialize some values in case of early error. */ memset(&rsp, 0, sizeof rsp); value = NULL; value_len = 0; rc = ble_hs_misc_pullup_base(rxom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ); if (rc != 0) { goto done; } ble_att_prep_write_rsp_parse((*rxom)->om_data, (*rxom)->om_len, &rsp); /* Strip the base from the front of the response. */ os_mbuf_adj(*rxom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ); /* Copy the attribute data into the global ATT flat buffer. */ rc = ble_att_clt_copy_attr_to_flatbuf(*rxom, &value, &value_len); done: /* Notify GATT client that the full response has been parsed. */ ble_gattc_rx_prep_write_rsp(conn_handle, rc, &rsp, value, value_len); return rc; }
static int ble_att_clt_parse_find_info_entry(struct os_mbuf **rxom, uint8_t rsp_format, struct ble_att_find_info_idata *idata) { uint16_t uuid16; int entry_len; int rc; switch (rsp_format) { case BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT: entry_len = 2 + 2; break; case BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT: entry_len = 2 + 16; break; default: return BLE_HS_EBADDATA; } rc = ble_hs_misc_pullup_base(rxom, entry_len); if (rc != 0) { return rc; } idata->attr_handle = le16toh((*rxom)->om_data); switch (rsp_format) { case BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT: uuid16 = le16toh((*rxom)->om_data + 2); rc = ble_uuid_16_to_128(uuid16, idata->uuid128); if (rc != 0) { return BLE_HS_EBADDATA; } break; case BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT: rc = os_mbuf_copydata(*rxom, 2, 16, idata->uuid128); if (rc != 0) { return BLE_HS_EBADDATA; } break; default: BLE_HS_DBG_ASSERT(0); break; } os_mbuf_adj(*rxom, entry_len); return 0; }
int ble_att_clt_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) { #if !NIMBLE_OPT(ATT_CLT_READ_GROUP_TYPE) return BLE_HS_ENOTSUP; #endif struct ble_att_read_group_type_adata adata; struct ble_att_read_group_type_rsp rsp; int rc; rc = ble_hs_misc_pullup_base(rxom, BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ); if (rc != 0) { goto done; } ble_att_read_group_type_rsp_parse((*rxom)->om_data, (*rxom)->om_len, &rsp); /* Strip the base from the front of the response. */ os_mbuf_adj(*rxom, BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ); /* Parse the Attribute Data List field, passing each entry to GATT. */ while (OS_MBUF_PKTLEN(*rxom) > 0) { rc = ble_att_clt_parse_read_group_type_adata(rxom, rsp.bagp_length, &adata); if (rc != 0) { goto done; } ble_gattc_rx_read_group_type_adata(conn_handle, &adata); os_mbuf_adj(*rxom, rsp.bagp_length); } done: /* Notify GATT that the response is done being parsed. */ ble_gattc_rx_read_group_type_complete(conn_handle, rc); return rc; }
static int host_hci_data_hdr_strip(struct os_mbuf *om, struct hci_data_hdr *hdr) { int rc; rc = os_mbuf_copydata(om, 0, BLE_HCI_DATA_HDR_SZ, hdr); if (rc != 0) { return BLE_HS_EMSGSIZE; } /* Strip HCI ACL data header from the front of the packet. */ os_mbuf_adj(om, BLE_HCI_DATA_HDR_SZ); hdr->hdh_handle_pb_bc = le16toh(&hdr->hdh_handle_pb_bc); hdr->hdh_len = le16toh(&hdr->hdh_len); return 0; }
static int ble_att_clt_tx_req_flags(uint16_t conn_handle, struct os_mbuf *txom, ble_hs_conn_flags_t flags_on_success) { struct ble_l2cap_chan *chan; struct ble_hs_conn *conn; uint16_t total_len; uint16_t mtu; int extra_len; int rc; BLE_HS_DBG_ASSERT_EVAL(txom->om_len >= 1); ble_att_inc_tx_stat(txom->om_data[0]); ble_hs_lock(); rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); if (rc == 0) { /* Reduce the size of the transmission to fit the connection's ATT * MTU. */ total_len = OS_MBUF_PKTLEN(txom); mtu = ble_l2cap_chan_mtu(chan); extra_len = total_len - mtu; if (extra_len > 0) { os_mbuf_adj(txom, -extra_len); } rc = ble_l2cap_tx(conn, chan, txom); txom = NULL; if (rc == 0) { conn->bhc_flags |= flags_on_success; } } ble_hs_unlock(); os_mbuf_free_chain(txom); return rc; }
int ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **om) { #if !NIMBLE_OPT(ATT_CLT_FIND_INFO) return BLE_HS_ENOTSUP; #endif struct ble_att_find_info_idata idata; struct ble_att_find_info_rsp rsp; int rc; rc = ble_hs_misc_pullup_base(om, BLE_ATT_FIND_INFO_RSP_BASE_SZ); if (rc != 0) { goto done; } ble_att_find_info_rsp_parse((*om)->om_data, (*om)->om_len, &rsp); /* Strip the response base from the front of the mbuf. */ os_mbuf_adj((*om), BLE_ATT_FIND_INFO_RSP_BASE_SZ); while (OS_MBUF_PKTLEN(*om) > 0) { rc = ble_att_clt_parse_find_info_entry(om, rsp.bafp_format, &idata); if (rc != 0) { goto done; } /* Hand find-info entry to GATT. */ ble_gattc_rx_find_info_idata(conn_handle, &idata); } rc = 0; done: /* Notify GATT that response processing is done. */ ble_gattc_rx_find_info_complete(conn_handle, rc); return rc; }
int ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom) { #if !NIMBLE_OPT(ATT_CLT_READ_MULT) return BLE_HS_ENOTSUP; #endif uint16_t value_len; void *value; int rc; /* Reponse consists of a one-byte opcode (already verified) and a variable * length Attribute Value field. Strip the opcode from the response. */ os_mbuf_adj(*rxom, BLE_ATT_READ_MULT_RSP_BASE_SZ); /* Copy the attribute data into the global ATT flat buffer. */ rc = ble_att_clt_copy_attr_to_flatbuf(*rxom, &value, &value_len); /* Pass the Attribute Value field to GATT. */ ble_gattc_rx_read_mult_rsp(conn_handle, rc, value, value_len); return rc; }
/** * ll tx pkt in proc * * Process ACL data packet input from host * * Context: Link layer task * */ static void ble_ll_tx_pkt_in(void) { uint16_t handle; uint16_t length; uint16_t pb; struct os_mbuf_pkthdr *pkthdr; struct os_mbuf *om; /* Drain all packets off the queue */ while (STAILQ_FIRST(&g_ble_ll_data.ll_tx_pkt_q)) { /* Get mbuf pointer from packet header pointer */ pkthdr = STAILQ_FIRST(&g_ble_ll_data.ll_tx_pkt_q); om = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf)); /* Remove from queue */ STAILQ_REMOVE_HEAD(&g_ble_ll_data.ll_tx_pkt_q, omp_next); /* Strip HCI ACL header to get handle and length */ handle = le16toh(om->om_data); length = le16toh(om->om_data + 2); os_mbuf_adj(om, sizeof(struct hci_data_hdr)); /* Do some basic error checking */ pb = handle & 0x3000; if ((pkthdr->omp_len != length) || (pb > 0x1000) || (length == 0)) { /* This is a bad ACL packet. Count a stat and free it */ STATS_INC(ble_ll_stats, bad_acl_hdr); os_mbuf_free_chain(om); continue; } /* Hand to connection state machine */ ble_ll_conn_tx_pkt_in(om, handle, length); } }
/* * Check for full packet. If frame is not right, free the mbuf. */ static void nmgr_uart_rx_pkt(struct nmgr_uart_state *nus, struct os_mbuf_pkthdr *rxm) { struct os_mbuf *m; struct nmgr_ser_hdr *nsh; uint16_t crc; int rc; m = OS_MBUF_PKTHDR_TO_MBUF(rxm); if (rxm->omp_len <= sizeof(uint16_t) + sizeof(crc)) { goto err; } nsh = (struct nmgr_ser_hdr *)m->om_data; switch (nsh->nsh_seq) { case htons(SHELL_NLIP_PKT): if (nus->nus_rx_pkt) { os_mbuf_free_chain(OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx_pkt)); nus->nus_rx_pkt = NULL; } break; case htons(SHELL_NLIP_DATA): if (!nus->nus_rx_pkt) { goto err; } break; default: goto err; } if (os_mbuf_append(m, "\0", 1)) { /* * Null-terminate the line for base64_decode's sake. */ goto err; } m = os_mbuf_pullup(m, rxm->omp_len); if (!m) { /* * Make data contiguous for base64_decode's sake. */ goto err; } rxm = OS_MBUF_PKTHDR(m); rc = base64_decode((char *)m->om_data + 2, (char *)m->om_data + 2); if (rc < 0) { goto err; } rxm->omp_len = m->om_len = rc + 2; if (nus->nus_rx_pkt) { os_mbuf_adj(m, 2); os_mbuf_concat(OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx_pkt), m); } else { nus->nus_rx_pkt = rxm; } m = OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx_pkt); nsh = (struct nmgr_ser_hdr *)m->om_data; if (nus->nus_rx_pkt->omp_len - sizeof(*nsh) == ntohs(nsh->nsh_len)) { os_mbuf_adj(m, 4); os_mbuf_adj(m, -2); nmgr_rx_req(&nus->nus_transport, m); nus->nus_rx_pkt = NULL; } return; err: os_mbuf_free_chain(m); }