예제 #1
0
/**
 * Called to reset the controller. This performs a "software reset" of the link
 * layer; it does not perform a HW reset of the controller nor does it reset
 * the HCI interface.
 *
 * Context: Link Layer task (HCI command)
 *
 * @return int The ble error code to place in the command complete event that
 * is returned when this command is issued.
 */
int
ble_ll_reset(void)
{
    int rc;
    os_sr_t sr;

    /* Stop the phy */
    ble_phy_disable();

    /* Stop any wait for response timer */
    OS_ENTER_CRITICAL(sr);
    ble_ll_wfr_disable();
    ble_ll_sched_stop();
    OS_EXIT_CRITICAL(sr);

    /* Stop any scanning */
    ble_ll_scan_reset();

    /* Stop any advertising */
    ble_ll_adv_reset();

    /* FLush all packets from Link layer queues */
    ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_tx_pkt_q);
    ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_rx_pkt_q);

    /* Reset LL stats */
    memset((uint8_t *)&ble_ll_stats + sizeof(struct stats_hdr), 0,
           sizeof(struct stats_ble_ll_stats) - sizeof(struct stats_hdr));

#ifdef BLE_LL_LOG
    g_ble_ll_log_index = 0;
    memset(&g_ble_ll_log, 0, sizeof(g_ble_ll_log));
#endif

    /* Reset connection module */
    ble_ll_conn_module_reset();

    /* All this does is re-initialize the event masks so call the hci init */
    ble_ll_hci_init();

    /* Set state to standby */
    ble_ll_state_set(BLE_LL_STATE_STANDBY);

    /* Reset our random address */
    memset(g_random_addr, 0, BLE_DEV_ADDR_LEN);

    /* Clear the whitelist */
    ble_ll_whitelist_clear();

    /* Reset resolving list */
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
    ble_ll_resolv_list_reset();
#endif

    /* Re-initialize the PHY */
    rc = ble_phy_init();

    return rc;
}
예제 #2
0
/**
 * Process a LE command sent from the host to the controller. The HCI command
 * has a 3 byte command header followed by data. The header is:
 *  -> opcode (2 bytes)
 *  -> Length of parameters (1 byte; does include command header bytes).
 *
 * @param cmdbuf Pointer to command buffer. Points to start of command header.
 * @param ocf    Opcode command field.
 * @param *rsplen Pointer to length of response
 *
 * @return int  This function returns a BLE error code. If a command status
 *              event should be returned as opposed to command complete,
 *              256 gets added to the return value.
 */
static int
ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
{
    int rc;
    uint8_t cmdlen;
    uint8_t len;
    uint8_t *rspbuf;

    /* Assume error; if all pass rc gets set to 0 */
    rc = BLE_ERR_INV_HCI_CMD_PARMS;

    /* Get length from command */
    len = cmdbuf[sizeof(uint16_t)];

    /* Check the length to make sure it is valid */
    cmdlen = g_ble_hci_le_cmd_len[ocf];
    if (len != cmdlen) {
        goto ll_hci_le_cmd_exit;
    }

    /*
     * The command response pointer points into the same buffer as the
     * command data itself. That is fine, as each command reads all the data
     * before crafting a response.
     */
    rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN;

    /* Move past HCI command header */
    cmdbuf += BLE_HCI_CMD_HDR_LEN;

    switch (ocf) {
    case BLE_HCI_OCF_LE_SET_EVENT_MASK:
        rc = ble_ll_hci_set_le_event_mask(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_RD_BUF_SIZE:
        rc = ble_ll_hci_le_read_bufsize(rspbuf, rsplen);
        break;
    case BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT:
        rc = ble_ll_hci_le_read_local_features(rspbuf, rsplen);
        break;
    case BLE_HCI_OCF_LE_SET_RAND_ADDR:
        rc = ble_ll_set_random_addr(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_SET_ADV_PARAMS:
        rc = ble_ll_adv_set_adv_params(cmdbuf, 0, 0);
        break;
    case BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR:
        rc = ble_ll_adv_read_txpwr(rspbuf, rsplen);
        break;
    case BLE_HCI_OCF_LE_SET_ADV_DATA:
        rc = ble_ll_adv_set_adv_data(cmdbuf, 0);
        break;
    case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA:
        rc = ble_ll_adv_set_scan_rsp_data(cmdbuf, 0);
        break;
    case BLE_HCI_OCF_LE_SET_ADV_ENABLE:
        rc = ble_ll_adv_set_enable(cmdbuf, 0);
        break;
    case BLE_HCI_OCF_LE_SET_SCAN_ENABLE:
        rc = ble_ll_scan_set_enable(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_SET_SCAN_PARAMS:
        rc = ble_ll_scan_set_scan_params(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_CREATE_CONN:
        rc = ble_ll_conn_create(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL:
        rc = ble_ll_conn_create_cancel();
        break;
    case BLE_HCI_OCF_LE_CLEAR_WHITE_LIST:
        rc = ble_ll_whitelist_clear();
        break;
    case BLE_HCI_OCF_LE_RD_WHITE_LIST_SIZE:
        rc = ble_ll_whitelist_read_size(rspbuf, rsplen);
        break;
    case BLE_HCI_OCF_LE_ADD_WHITE_LIST:
        rc = ble_ll_whitelist_add(cmdbuf + 1, cmdbuf[0]);
        break;
    case BLE_HCI_OCF_LE_RMV_WHITE_LIST:
        rc = ble_ll_whitelist_rmv(cmdbuf + 1, cmdbuf[0]);
        break;
    case BLE_HCI_OCF_LE_CONN_UPDATE:
        rc = ble_ll_conn_hci_update(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS:
        rc = ble_ll_conn_hci_set_chan_class(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_RD_CHAN_MAP:
        rc = ble_ll_conn_hci_rd_chan_map(cmdbuf, rspbuf, rsplen);
        break;
    case BLE_HCI_OCF_LE_RD_REM_FEAT:
        rc = ble_ll_conn_hci_read_rem_features(cmdbuf);
        break;
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
    case BLE_HCI_OCF_LE_ENCRYPT:
        rc = ble_ll_hci_le_encrypt(cmdbuf, rspbuf, rsplen);
        break;
#endif
    case BLE_HCI_OCF_LE_RAND:
        rc = ble_ll_hci_le_rand(rspbuf, rsplen);
        break;
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
    case BLE_HCI_OCF_LE_START_ENCRYPT:
        rc = ble_ll_conn_hci_le_start_encrypt(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY:
    case BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY:
        rc = ble_ll_conn_hci_le_ltk_reply(cmdbuf, rspbuf, ocf);
        *rsplen = sizeof(uint16_t);
        break;
#endif
    case BLE_HCI_OCF_LE_RD_SUPP_STATES :
        rc = ble_ll_hci_le_read_supp_states(rspbuf, rsplen);
        break;
    case BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR:
        rc = ble_ll_conn_hci_param_reply(cmdbuf, 0);
        break;
    case BLE_HCI_OCF_LE_REM_CONN_PARAM_RR:
        rc = ble_ll_conn_hci_param_reply(cmdbuf, 1);
        break;
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) == 1)
    case BLE_HCI_OCF_LE_SET_DATA_LEN:
        rc = ble_ll_conn_hci_set_data_len(cmdbuf, rspbuf, rsplen);
        break;
    case BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN:
        rc = ble_ll_hci_le_rd_sugg_data_len(rspbuf, rsplen);
        break;
    case BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN:
        rc = ble_ll_hci_le_wr_sugg_data_len(cmdbuf);
        break;
#endif
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
    case BLE_HCI_OCF_LE_ADD_RESOLV_LIST :
        rc = ble_ll_resolv_list_add(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_RMV_RESOLV_LIST:
        rc = ble_ll_resolv_list_rmv(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_CLR_RESOLV_LIST:
        rc = ble_ll_resolv_list_clr();
        break;
    case BLE_HCI_OCF_LE_RD_RESOLV_LIST_SIZE:
        rc = ble_ll_resolv_list_read_size(rspbuf, rsplen);
        break;
    case BLE_HCI_OCF_LE_RD_PEER_RESOLV_ADDR:
        rc = ble_ll_resolv_peer_addr_rd(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR:
        ble_ll_resolv_local_addr_rd(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_SET_ADDR_RES_EN:
        rc = ble_ll_resolv_enable_cmd(cmdbuf);
        break;
    case BLE_HCI_OCF_LE_SET_RPA_TMO:
        rc = ble_ll_resolv_set_rpa_tmo(cmdbuf);
        break;
#endif
    case BLE_HCI_OCF_LE_RD_MAX_DATA_LEN:
        rc = ble_ll_hci_le_rd_max_data_len(rspbuf, rsplen);
        break;
    default:
        rc = BLE_ERR_UNKNOWN_HCI_CMD;
        break;
    }

    /*
     * This code is here because we add 256 to the return code to denote
     * that the reply to this command should be command status (as opposed to
     * command complete).
     */
ll_hci_le_cmd_exit:
    if (ble_ll_hci_le_cmd_send_cmd_status(ocf)) {
        rc += (BLE_ERR_MAX + 1);
    }

    return rc;
}