/** * Called to put a packet on the Link Layer receive packet queue. * * @param rxpdu Pointer to received PDU */ void ble_ll_rx_pdu_in(struct os_mbuf *rxpdu) { struct os_mbuf_pkthdr *pkthdr; pkthdr = OS_MBUF_PKTHDR(rxpdu); STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_rx_pkt_q, pkthdr, omp_next); os_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_rx_pkt_ev); }
/** * Called to indicate the advertising event is over. * * Context: Interrupt * * @param advsm * */ static void ble_ll_adv_tx_done(void *arg) { struct ble_ll_adv_sm *advsm; advsm = (struct ble_ll_adv_sm *)arg; os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); ble_ll_log(BLE_LL_LOG_ID_ADV_TXDONE, ble_ll_state_get(), 0, 0); ble_ll_state_set(BLE_LL_STATE_STANDBY); }
/** * Called to put a packet on the Link Layer transmit packet queue. * * @param txpdu Pointer to transmit packet */ void ble_ll_acl_data_in(struct os_mbuf *txpkt) { os_sr_t sr; struct os_mbuf_pkthdr *pkthdr; pkthdr = OS_MBUF_PKTHDR(txpkt); OS_ENTER_CRITICAL(sr); STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_tx_pkt_q, pkthdr, omp_next); OS_EXIT_CRITICAL(sr); os_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_tx_pkt_ev); }
int ble_hs_tx_data(struct os_mbuf *om) { int rc; rc = os_mqueue_put(&ble_hs_tx_q, &ble_hs_evq, om); if (rc != 0) { return BLE_HS_EOS; } os_eventq_put(ble_hs_parent_evq, &ble_hs_event_co.cf_c.c_ev); return 0; }
/* * Receive a character from UART. */ static int nmgr_uart_rx_char(void *arg, uint8_t data) { struct nmgr_uart_state *nus = (struct nmgr_uart_state *)arg; struct os_mbuf *m; int rc; if (!nus->nus_rx) { m = os_msys_get_pkthdr(SHELL_NLIP_MAX_FRAME, 0); if (!m) { return 0; } nus->nus_rx = OS_MBUF_PKTHDR(m); if (OS_MBUF_TRAILINGSPACE(m) < SHELL_NLIP_MAX_FRAME) { /* * mbuf is too small. */ os_mbuf_free_chain(m); nus->nus_rx = NULL; return 0; } } m = OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx); if (data == '\n') { /* * Full line of input. Process it outside interrupt context. */ assert(!nus->nus_rx_q); nus->nus_rx_q = nus->nus_rx; nus->nus_rx = NULL; os_eventq_put(g_mgmt_evq, &nus->nus_cb_ev); return 0; } else { rc = os_mbuf_append(m, &data, 1); if (rc == 0) { return 0; } } /* failed */ nus->nus_rx->omp_len = 0; m->om_len = 0; os_mbuf_free_chain(SLIST_NEXT(m, om_next)); SLIST_NEXT(m, om_next) = NULL; return 0; }
/** * Sends an HCI command to the controller. On success, the supplied buffer is * relinquished to the controller task. On failure, the caller must free the * buffer. * * @param cmd A flat buffer containing the HCI command to * send. * * @return 0 on success; * BLE_ERR_MEM_CAPACITY on HCI buffer exhaustion. */ int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg) { struct os_event *ev; /* Get an event structure off the queue */ ev = &g_ble_ll_hci_cmd_ev; if (ev->ev_queued) { return BLE_ERR_MEM_CAPACITY; } /* Fill out the event and post to Link Layer */ ev->ev_queued = 0; ev->ev_arg = cmd; os_eventq_put(&g_ble_ll_data.ll_evq, ev); return 0; }
/* XXX: For now, put this here */ int ble_hci_transport_ctlr_event_send(uint8_t *hci_ev) { os_error_t err; struct os_event *ev; assert(hci_ev != NULL); /* Get an event structure off the queue */ ev = (struct os_event *)os_memblock_get(&g_hci_os_event_pool); if (!ev) { err = os_memblock_put(&g_hci_cmd_pool, hci_ev); assert(err == OS_OK); return -1; } /* Fill out the event and post to Link Layer */ ev->ev_queued = 0; ev->ev_type = BLE_HOST_HCI_EVENT_CTLR_EVENT; ev->ev_arg = hci_ev; os_eventq_put(&ble_hs_evq, ev); return 0; }
/** * Called when an advertising event is over. * * Context: Link Layer task. * * @param arg Pointer to advertising state machine. */ static void ble_ll_adv_done(struct ble_ll_adv_sm *advsm) { uint8_t mask; uint8_t final_adv_chan; int32_t delta_t; uint32_t itvl; uint32_t start_time; assert(advsm->enabled); /* Remove the element from the schedule if it is still there. */ ble_ll_sched_rmv_elem(&advsm->adv_sch); os_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); /* * Check if we have ended our advertising event. If our last advertising * packet was sent on the last channel, it means we are done with this * event. */ if (advsm->adv_chanmask & 0x04) { final_adv_chan = BLE_PHY_ADV_CHAN_START + 2; } else if (advsm->adv_chanmask & 0x02) { final_adv_chan = BLE_PHY_ADV_CHAN_START + 1; } else { final_adv_chan = BLE_PHY_ADV_CHAN_START; } if (advsm->adv_chan == final_adv_chan) { /* Check if we need to resume scanning */ ble_ll_scan_chk_resume(); /* This event is over. Set adv channel to first one */ advsm->adv_chan = ble_ll_adv_first_chan(advsm); /* Calculate start time of next advertising event */ itvl = advsm->adv_itvl_usecs; if (advsm->adv_type != BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) { itvl += rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000); } advsm->adv_event_start_time += os_cputime_usecs_to_ticks(itvl); advsm->adv_pdu_start_time = advsm->adv_event_start_time; /* * The scheduled time better be in the future! If it is not, we will * just keep advancing until we the time is in the future */ start_time = advsm->adv_pdu_start_time - os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS); delta_t = (int32_t)(start_time - os_cputime_get32()); if (delta_t < 0) { /* Calculate start time of next advertising event */ while (delta_t < 0) { itvl = advsm->adv_itvl_usecs; if (advsm->adv_type != BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) { itvl += rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000); } itvl = os_cputime_usecs_to_ticks(itvl); advsm->adv_event_start_time += itvl; advsm->adv_pdu_start_time = advsm->adv_event_start_time; delta_t += (int32_t)itvl; } } } else { /* * Move to next advertising channel. If not in the mask, just * increment by 1. We can do this because we already checked if we * just transmitted on the last advertising channel */ ++advsm->adv_chan; mask = 1 << (advsm->adv_chan - BLE_PHY_ADV_CHAN_START); if ((mask & advsm->adv_chanmask) == 0) { ++advsm->adv_chan; } /* * We will transmit right away. Set next pdu start time to now * plus a xcvr start delay just so we dont count late adv starts */ advsm->adv_pdu_start_time = os_cputime_get32() + os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS); } /* * Stop high duty cycle directed advertising if we have been doing * it for more than 1.28 seconds */ if (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) { if (advsm->adv_pdu_start_time >= advsm->adv_dir_hd_end_time) { /* Disable advertising */ advsm->enabled = 0; ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO, advsm->conn_comp_ev); advsm->conn_comp_ev = NULL; ble_ll_scan_chk_resume(); return; } } /* We need to regenerate our RPA's if we have passed timeout */ #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) ble_ll_adv_chk_rpa_timeout(advsm); #endif /* Schedule advertising transmit */ ble_ll_adv_set_sched(advsm, 0); /* * In the unlikely event we cant reschedule this, just post a done * event and we will reschedule the next advertising event */ if (ble_ll_sched_adv_reschedule(&advsm->adv_sch)) { os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); } }
void ble_hs_event_enqueue(struct os_event *ev) { os_eventq_put(&ble_hs_evq, ev); os_eventq_put(ble_hs_parent_evq, &ble_hs_event_co.cf_c.c_ev); }
/** * Called to post event to Link Layer when a data buffer overflow has * occurred. * * Context: Interrupt * */ void ble_ll_data_buffer_overflow(void) { os_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_dbuf_overflow_ev); }
/** * ble ll event send * * Send an event to the Link Layer task * * @param ev Event to add to the Link Layer event queue. */ void ble_ll_event_send(struct os_event *ev) { os_eventq_put(&g_ble_ll_data.ll_evq, ev); }
/** * ADP5061 IRQ * Add interrupt handling task to queue */ static void adp5061_isr(void *arg){ os_eventq_put(os_eventq_dflt_get(), &interrup_handler); }