Example #1
0
/**
 * 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);
}
Example #3
0
/**
 * 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);
}
Example #4
0
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;
}
Example #5
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;
}
Example #7
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);
    }
}
Example #9
0
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);
}
Example #10
0
/**
 * 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);
}
Example #11
0
/**
 * 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);
}