/** * Process a received packet at the link layer task when in the advertising * state * * Context: Link Layer * * * @param ptype * @param rxbuf * @param hdr * * @return int */ void ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) { int adv_event_over; /* * If we have received a scan request and we are transmitting a response * or we have received a valid connect request, dont "end" the advertising * event. In the case of a connect request we will stop advertising. In * the case of the scan response transmission we will get a transmit * end callback. */ adv_event_over = 1; if (BLE_MBUF_HDR_CRC_OK(hdr)) { if (ptype == BLE_ADV_PDU_TYPE_CONNECT_REQ) { if (ble_ll_adv_conn_req_rxd(rxbuf, hdr)) { adv_event_over = 0; } } else { if ((ptype == BLE_ADV_PDU_TYPE_SCAN_REQ) && (hdr->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_TXD)) { adv_event_over = 0; } } } if (adv_event_over) { ble_ll_adv_event_done(&g_ble_ll_adv_sm); } }
/** * Count Link Layer statistics for received PDUs * * Context: Link layer task * * @param hdr * @param len */ static void ble_ll_count_rx_stats(struct ble_mbuf_hdr *hdr, uint16_t len, uint8_t pdu_type) { uint8_t crcok; uint8_t chan; crcok = BLE_MBUF_HDR_CRC_OK(hdr); chan = hdr->rxinfo.channel; if (crcok) { if (chan < BLE_PHY_NUM_DATA_CHANS) { STATS_INC(ble_ll_stats, rx_data_pdu_crc_ok); STATS_INCN(ble_ll_stats, rx_data_bytes_crc_ok, len); } else { STATS_INC(ble_ll_stats, rx_adv_pdu_crc_ok); STATS_INCN(ble_ll_stats, rx_adv_bytes_crc_ok, len); ble_ll_count_rx_adv_pdus(pdu_type); } } else { if (chan < BLE_PHY_NUM_DATA_CHANS) { STATS_INC(ble_ll_stats, rx_data_pdu_crc_err); STATS_INCN(ble_ll_stats, rx_data_bytes_crc_err, len); } else { STATS_INC(ble_ll_stats, rx_adv_pdu_crc_err); STATS_INCN(ble_ll_stats, rx_adv_bytes_crc_err, len); } } }
/** * Process a received packet at the link layer task when in the advertising * state * * Context: Link Layer * * * @param ptype * @param rxbuf * @param hdr * * @return int */ void ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) { int adv_event_over; /* * It is possible that advertising was stopped and a packet plcaed on the * LL receive packet queue. In this case, just ignore the received packet * as the advertising state machine is no longer "valid" */ if (!g_ble_ll_adv_sm.enabled) { return; } /* * If we have received a scan request and we are transmitting a response * or we have received a valid connect request, dont "end" the advertising * event. In the case of a connect request we will stop advertising. In * the case of the scan response transmission we will get a transmit * end callback. */ adv_event_over = 1; if (BLE_MBUF_HDR_CRC_OK(hdr)) { if (ptype == BLE_ADV_PDU_TYPE_CONNECT_REQ) { if (ble_ll_adv_conn_req_rxd(rxbuf, hdr)) { adv_event_over = 0; } } else { if ((ptype == BLE_ADV_PDU_TYPE_SCAN_REQ) && (hdr->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_TXD)) { adv_event_over = 0; } } } if (adv_event_over) { ble_ll_adv_done(&g_ble_ll_adv_sm); } }
/** * Called by the PHY when a receive packet has ended. * * NOTE: Called from interrupt context! * * @param rxbuf Pointer to received PDU data * rxhdr Pointer to BLE header of received mbuf * * @return int * < 0: Disable the phy after reception. * == 0: Success. Do not disable the PHY. * > 0: Do not disable PHY as that has already been done. */ int ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) { int rc; int badpkt; uint8_t pdu_type; uint8_t len; uint8_t chan; uint8_t crcok; struct os_mbuf *rxpdu; /* Get channel and CRC status from BLE header */ chan = rxhdr->rxinfo.channel; crcok = BLE_MBUF_HDR_CRC_OK(rxhdr); ble_ll_log(BLE_LL_LOG_ID_RX_END, rxbuf[0], ((uint16_t)rxhdr->rxinfo.flags << 8) | rxbuf[1], rxhdr->beg_cputime); /* Check channel type */ if (chan < BLE_PHY_NUM_DATA_CHANS) { /* * Data channel pdu. We should be in CONNECTION state with an * ongoing connection. */ rc = ble_ll_conn_rx_isr_end(rxbuf, rxhdr); return rc; } /* Get advertising PDU type and length */ pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK; /* If the CRC checks, make sure lengths check! */ badpkt = 0; if (crcok) { switch (pdu_type) { case BLE_ADV_PDU_TYPE_SCAN_REQ: case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: if (len != BLE_SCAN_REQ_LEN) { badpkt = 1; } break; case BLE_ADV_PDU_TYPE_SCAN_RSP: case BLE_ADV_PDU_TYPE_ADV_IND: case BLE_ADV_PDU_TYPE_ADV_SCAN_IND: case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND: if ((len < BLE_DEV_ADDR_LEN) || (len > BLE_ADV_SCAN_IND_MAX_LEN)) { badpkt = 1; } break; case BLE_ADV_PDU_TYPE_CONNECT_REQ: if (len != BLE_CONNECT_REQ_LEN) { badpkt = 1; } break; default: badpkt = 1; break; } /* If this is a malformed packet, just kill it here */ if (badpkt) { STATS_INC(ble_ll_stats, rx_adv_malformed_pkts); } } /* Hand packet to the appropriate state machine (if crc ok) */ rxpdu = NULL; switch (BLE_MBUF_HDR_RX_STATE(rxhdr)) { case BLE_LL_STATE_ADV: if (!badpkt) { rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN); if (rxpdu) { ble_phy_rxpdu_copy(rxbuf, rxpdu); } } rc = ble_ll_adv_rx_isr_end(pdu_type, rxpdu, crcok); break; case BLE_LL_STATE_SCANNING: if (!badpkt) { rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN); if (rxpdu) { ble_phy_rxpdu_copy(rxbuf, rxpdu); } } rc = ble_ll_scan_rx_isr_end(rxpdu, crcok); break; case BLE_LL_STATE_INITIATING: rc = ble_ll_init_rx_isr_end(rxbuf, crcok, rxhdr); break; default: rc = -1; STATS_INC(ble_ll_stats, bad_ll_state); break; } /* Hand packet up to higher layer (regardless of CRC failure) */ if (rxpdu) { ble_ll_rx_pdu_in(rxpdu); } return rc; }