/** * 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; }
/** * 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; }