blob: 135687849be0f9c4564ae5aebf7961e6b901e34c [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <assert.h>
#include <string.h>
#include "os/os.h"
#include "bsp/bsp.h"
#include "hal/hal_gpio.h"
#include "hal/hal_cputime.h"
#include "hal/hal_flash.h"
#include "console/console.h"
#include "shell/shell.h"
#include "stats/stats.h"
#include "hal/flash_map.h"
#include "fs/fs.h"
#include "nffs/nffs.h"
#include "newtmgr/newtmgr.h"
#include "imgmgr/imgmgr.h"
/* BLE */
#include "nimble/ble.h"
#include "nimble/hci_transport.h"
#include "nimble/hci_common.h"
#include "host/host_hci.h"
#include "host/ble_hs.h"
#include "controller/ble_ll.h"
#include "controller/ble_ll_hci.h"
#include "controller/ble_ll_conn.h"
#include "controller/ble_ll_scan.h"
#include "controller/ble_ll_adv.h"
/* Task priorities */
/* NOTE: highest priority task (0) reserved for controller LL task */
#define HOST_TASK_PRIO (OS_TASK_PRI_HIGHEST + 1)
#define BLETEST_TASK_PRIO (HOST_TASK_PRIO + 1)
#define SHELL_TASK_PRIO (BLETEST_TASK_PRIO + 1)
#define NEWTMGR_TASK_PRIO (SHELL_TASK_PRIO + 1)
/* Shell task stack */
#define SHELL_TASK_STACK_SIZE (OS_STACK_ALIGN(256))
os_stack_t shell_stack[SHELL_TASK_STACK_SIZE];
/* Newt manager task stack */
#define NEWTMGR_TASK_STACK_SIZE (OS_STACK_ALIGN(448))
os_stack_t newtmgr_stack[NEWTMGR_TASK_STACK_SIZE];
/* Flash file system sector size */
#define NFFS_AREA_MAX (8)
/* Shell maximum input line length */
#define SHELL_MAX_INPUT_LEN (256)
/* For LED toggling */
int g_led_pin;
/* Our global device address (public) */
uint8_t g_dev_addr[BLE_DEV_ADDR_LEN];
/* Our random address (in case we need it) */
uint8_t g_random_addr[BLE_DEV_ADDR_LEN];
/* A buffer for host advertising data */
uint8_t g_host_adv_data[BLE_HCI_MAX_ADV_DATA_LEN];
uint8_t g_host_adv_len;
/* Create a mbuf pool of BLE mbufs */
#define MBUF_NUM_MBUFS (42)
#define MBUF_BUF_SIZE OS_ALIGN(BLE_MBUF_PAYLOAD_SIZE, 4)
#define MBUF_MEMBLOCK_SIZE (MBUF_BUF_SIZE + BLE_MBUF_MEMBLOCK_OVERHEAD)
#define MBUF_MEMPOOL_SIZE OS_MEMPOOL_SIZE(MBUF_NUM_MBUFS, MBUF_MEMBLOCK_SIZE)
struct os_mbuf_pool g_mbuf_pool;
struct os_mempool g_mbuf_mempool;
os_membuf_t g_mbuf_buffer[MBUF_MEMPOOL_SIZE];
/* Some application configurations */
#define BLETEST_ROLE_ADVERTISER (0)
#define BLETEST_ROLE_SCANNER (1)
#define BLETEST_ROLE_INITIATOR (2)
//#define BLETEST_CFG_ROLE (BLETEST_ROLE_INITIATOR)
#define BLETEST_CFG_ROLE (BLETEST_ROLE_ADVERTISER)
//#define BLETEST_CFG_ROLE (BLETEST_ROLE_SCANNER)
#define BLETEST_CFG_FILT_DUP_ADV (0)
#define BLETEST_CFG_ADV_ITVL (60000 / BLE_HCI_ADV_ITVL)
#define BLETEST_CFG_ADV_TYPE BLE_HCI_ADV_TYPE_ADV_IND
#define BLETEST_CFG_ADV_FILT_POLICY (BLE_HCI_ADV_FILT_NONE)
#define BLETEST_CFG_SCAN_ITVL (700000 / BLE_HCI_SCAN_ITVL)
#define BLETEST_CFG_SCAN_WINDOW (700000 / BLE_HCI_SCAN_ITVL)
#define BLETEST_CFG_SCAN_TYPE (BLE_HCI_SCAN_TYPE_ACTIVE)
#define BLETEST_CFG_SCAN_FILT_POLICY (BLE_HCI_SCAN_FILT_NO_WL)
#define BLETEST_CFG_CONN_ITVL (64) /* in 1.25 msec increments */
#define BLETEST_CFG_SLAVE_LATENCY (0)
#define BLETEST_CFG_INIT_FILTER_POLICY (BLE_HCI_CONN_FILT_NO_WL)
#define BLETEST_CFG_CONN_SPVN_TMO (1000) /* 20 seconds */
#define BLETEST_CFG_MIN_CE_LEN (6)
#define BLETEST_CFG_MAX_CE_LEN (BLETEST_CFG_CONN_ITVL)
#define BLETEST_CFG_CONCURRENT_CONNS (16)
/* BLETEST variables */
#undef BLETEST_ADV_PKT_NUM
#define BLETEST_PKT_SIZE (64)
#define BLETEST_STACK_SIZE (256)
uint32_t g_next_os_time;
int g_bletest_state;
struct os_eventq g_bletest_evq;
struct os_callout_func g_bletest_timer;
struct os_task bletest_task;
bssnz_t os_stack_t bletest_stack[BLETEST_STACK_SIZE];
uint32_t g_bletest_conn_end;
int g_bletest_start_update;
uint32_t g_bletest_conn_upd_time;
uint8_t g_bletest_current_conns;
uint8_t g_bletest_cur_peer_addr[BLE_DEV_ADDR_LEN];
uint8_t g_last_handle_used;
uint8_t g_bletest_led_state;
uint32_t g_bletest_led_rate;
uint32_t g_bletest_next_led_time;
#ifdef BLETEST_ADV_PKT_NUM
void
bletest_inc_adv_pkt_num(void)
{
int rc;
uint8_t *dptr;
uint8_t digit;
if (g_host_adv_len != 0) {
dptr = &g_host_adv_data[18];
while (dptr >= &g_host_adv_data[13]) {
digit = *dptr;
++digit;
if (digit == 58) {
digit = 48;
*dptr = digit;
--dptr;
} else {
*dptr = digit;
break;
}
}
rc = host_hci_cmd_le_set_adv_data(g_host_adv_data, g_host_adv_len);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
}
}
#endif
void
bletest_send_conn_update(uint16_t handle)
{
int rc;
struct hci_conn_update hcu;
hcu.conn_latency = 4;
hcu.supervision_timeout = 2000;
hcu.conn_itvl_min = 1000;
hcu.conn_itvl_max = 1000;
hcu.handle = handle;
hcu.min_ce_len = 4;
hcu.max_ce_len = 4;
rc = host_hci_cmd_le_conn_update(&hcu);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
}
/**
* Sets the advertising data to be sent in advertising pdu's which contain
* advertising data.
*
* @param dptr
* @return uint8_t
*/
uint8_t
bletest_set_adv_data(uint8_t *dptr)
{
uint8_t len;
/* Place flags in first */
dptr[0] = 2;
dptr[1] = 0x01; /* Flags identifier */
dptr[2] = 0x06;
dptr += 3;
len = 3;
/* Add local name */
dptr[0] = 15; /* Length of this data, not including the length */
dptr[1] = 0x09;
dptr[2] = 'r';
dptr[3] = 'u';
dptr[4] = 'n';
dptr[5] = 't';
dptr[6] = 'i';
dptr[7] = 'm';
dptr[8] = 'e';
dptr[9] = '-';
dptr[10] = '0';
dptr[11] = '0';
dptr[12] = '0';
dptr[13] = '0';
dptr[14] = '0';
dptr[15] = '0';
dptr += 16;
len += 16;
/* Add local device address */
dptr[0] = 0x08;
dptr[1] = 0x1B;
dptr[2] = 0x00;
memcpy(dptr + 3, g_dev_addr, BLE_DEV_ADDR_LEN);
len += 9;
g_host_adv_len = len;
return len;
}
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER)
void
bletest_init_advertising(void)
{
int rc;
uint8_t adv_len;
struct hci_adv_params adv;
/* Just zero out advertising */
memset(&adv, 0, sizeof(struct hci_adv_params));
/* Set advertising parameters */
adv.adv_type = BLETEST_CFG_ADV_TYPE;
adv.adv_channel_map = 0x07;
adv.adv_filter_policy = BLETEST_CFG_ADV_FILT_POLICY;
adv.own_addr_type = BLE_HCI_ADV_OWN_ADDR_PUBLIC;
adv.peer_addr_type = BLE_HCI_ADV_PEER_ADDR_PUBLIC;
if ((adv.adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) ||
(adv.adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD)) {
memcpy(adv.peer_addr, g_bletest_cur_peer_addr, BLE_DEV_ADDR_LEN);
adv_len = 0;
} else {
adv_len = bletest_set_adv_data(&g_host_adv_data[0]);
}
console_printf("Trying to connect to %x.%x.%x.%x.%x.%x\n",
adv.peer_addr[0], adv.peer_addr[1], adv.peer_addr[2],
adv.peer_addr[3], adv.peer_addr[4], adv.peer_addr[5]);
if (adv.adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) {
adv.adv_itvl_min = 0;
adv.adv_itvl_max = 0;
} else {
adv.adv_itvl_min = BLETEST_CFG_ADV_ITVL;
adv.adv_itvl_max = BLETEST_CFG_ADV_ITVL; /* Advertising interval */
}
/* Set the advertising parameters */
rc = host_hci_cmd_le_set_adv_params(&adv);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
/* Set advertising data */
if (adv_len != 0) {
rc = host_hci_cmd_le_set_adv_data(&g_host_adv_data[0], adv_len);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
/* Set scan response data */
rc = host_hci_cmd_le_set_scan_rsp_data(&g_host_adv_data[0], adv_len);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
}
}
#endif
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_SCANNER)
void
bletest_init_scanner(void)
{
int rc;
uint8_t dev_addr[BLE_DEV_ADDR_LEN];
uint8_t filter_policy;
/* Set scanning parameters */
rc = host_hci_cmd_le_set_scan_params(BLETEST_CFG_SCAN_TYPE,
BLETEST_CFG_SCAN_ITVL,
BLETEST_CFG_SCAN_WINDOW,
BLE_HCI_ADV_OWN_ADDR_PUBLIC,
BLETEST_CFG_SCAN_FILT_POLICY);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
filter_policy = BLETEST_CFG_SCAN_FILT_POLICY;
if (filter_policy & 1) {
/* Add some whitelist addresses */
dev_addr[0] = 0x00;
dev_addr[1] = 0x00;
dev_addr[2] = 0x00;
dev_addr[3] = 0x88;
dev_addr[4] = 0x88;
dev_addr[5] = 0x08;
rc = host_hci_cmd_le_add_to_whitelist(dev_addr, BLE_ADDR_TYPE_PUBLIC);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
}
}
void
bletest_execute_scanner(void)
{
int rc;
/* Enable scanning */
if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
if (g_bletest_state) {
rc = host_hci_cmd_le_set_scan_enable(0, BLETEST_CFG_FILT_DUP_ADV);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
g_bletest_state = 0;
} else {
rc = host_hci_cmd_le_set_scan_enable(1, BLETEST_CFG_FILT_DUP_ADV);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
g_bletest_state = 1;
}
g_next_os_time += (OS_TICKS_PER_SEC * 60);
}
}
#endif
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_INITIATOR)
void
bletest_init_initiator(void)
{
int rc;
struct hci_create_conn cc;
struct hci_create_conn *hcc;
/* Enable initiating */
hcc = &cc;
hcc->conn_itvl_max = BLETEST_CFG_CONN_ITVL;
hcc->conn_itvl_min = BLETEST_CFG_CONN_ITVL;
hcc->conn_latency = BLETEST_CFG_SLAVE_LATENCY;
hcc->filter_policy = BLETEST_CFG_INIT_FILTER_POLICY;
hcc->supervision_timeout = BLETEST_CFG_CONN_SPVN_TMO;
hcc->scan_itvl = BLETEST_CFG_SCAN_ITVL;
hcc->scan_window = BLETEST_CFG_SCAN_WINDOW;
hcc->peer_addr_type = BLE_HCI_CONN_PEER_ADDR_PUBLIC;
memcpy(hcc->peer_addr, g_bletest_cur_peer_addr, BLE_DEV_ADDR_LEN);
hcc->own_addr_type = BLE_HCI_CONN_PEER_ADDR_PUBLIC;
hcc->min_ce_len = BLETEST_CFG_MIN_CE_LEN;
hcc->max_ce_len = BLETEST_CFG_MAX_CE_LEN;
console_printf("Trying to connect to %x.%x.%x.%x.%x.%x\n",
hcc->peer_addr[0], hcc->peer_addr[1], hcc->peer_addr[2],
hcc->peer_addr[3], hcc->peer_addr[4], hcc->peer_addr[5]);
rc = host_hci_cmd_le_create_connection(hcc);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
}
void
bletest_execute_initiator(void)
{
// int i;
int rc;
uint16_t handle;
/*
* Determine if there is an active connection for the current handle
* we are trying to create. If so, start looking for the next one
*/
if (g_bletest_current_conns < BLETEST_CFG_CONCURRENT_CONNS) {
handle = g_bletest_current_conns + 1;
if (ble_ll_conn_find_active_conn(handle)) {
/* Set LED to slower blink rate */
g_bletest_led_rate = OS_TICKS_PER_SEC;
/* Ask for version information */
rc = host_hci_cmd_rd_rem_version(handle);
host_hci_outstanding_opcode = 0;
/* Scanning better be stopped! */
assert(ble_ll_scan_enabled() == 0);
/* Add to current connections */
if (!rc) {
++g_bletest_current_conns;
/* Move to next connection */
if (g_bletest_current_conns < BLETEST_CFG_CONCURRENT_CONNS) {
/* restart initiating */
g_bletest_cur_peer_addr[5] += 1;
g_dev_addr[5] += 1;
bletest_init_initiator();
}
}
}
} else {
#if 0
if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
for (i = 0; i < g_bletest_current_conns; ++i) {
if (ble_ll_conn_find_active_conn(i + 1)) {
/* Ask for version information */
host_hci_cmd_read_rssi(i+1);
host_hci_outstanding_opcode = 0;
#if 0
bletest_send_conn_update(1);
#endif
}
}
g_next_os_time = os_time_get() + OS_TICKS_PER_SEC * 5;
}
#endif
}
}
#endif
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER)
/*
* Test wrapper to get packets. Only get a packet if we have more than half
* left
*/
static struct os_mbuf *
bletest_get_packet(void)
{
struct os_mbuf *om;
om = NULL;
if (g_mbuf_pool.omp_pool->mp_num_free >= 5) {
ble_get_packet(om);
}
return om;
}
#if 0
void
bletest_execute(void)
{
int rc;
int i;
uint16_t pktlen;
uint16_t handle;
struct os_mbuf *om;
struct ble_ll_conn_sm *connsm;
handle = 1;
if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
if (g_bletest_state == 0) {
rc = host_hci_cmd_le_set_adv_enable(1);
host_hci_outstanding_opcode = 0;
assert(rc == 0);
g_bletest_state = 1;
} else if (g_bletest_state == 1) {
/* See if handle 1 has been created. If so, send packets */
connsm = ble_ll_conn_find_active_conn(handle);
if (connsm) {
/* Set connection end time */
g_bletest_conn_end = os_time_get() +
(OS_TICKS_PER_SEC * (60 * 15));
g_bletest_state = 2;
}
} else if (g_bletest_state == 2) {
if ((int32_t)(os_time_get() - g_bletest_conn_end) >= 0) {
g_bletest_state = 3;
host_hci_cmd_disconnect(handle, BLE_ERR_REM_USER_CONN_TERM);
} else {
om = bletest_get_packet();
if (om) {
/* set payload length */
pktlen = BLETEST_PKT_SIZE;
om->om_len = BLETEST_PKT_SIZE + 4;
/* Put the HCI header in the mbuf */
htole16(om->om_data, handle);
htole16(om->om_data + 2, om->om_len);
/* Place L2CAP header in packet */
htole16(om->om_data + 4, pktlen);
om->om_data[6] = 0;
om->om_data[7] = 0;
/* Fill with incrementing pattern (starting from 1) */
for (i = 0; i < pktlen; ++i) {
om->om_data[8 + i] = (uint8_t)(i + 1);
}
/* Add length */
om->om_len += 4;
OS_MBUF_PKTHDR(om)->omp_len = om->om_len;
ble_hci_transport_host_acl_data_send(om);
}
g_next_os_time += OS_TICKS_PER_SEC / 10;
return;
}
} else if (g_bletest_state == 3) {
/* We should be waiting for disconnect */
connsm = ble_ll_conn_find_active_conn(handle);
if (!connsm) {
/* Set to 0 if you want to restart advertising */
//g_bletest_state = 0;
g_bletest_state = 4;
}
}
g_next_os_time += OS_TICKS_PER_SEC;
}
}
#else
static void
bletest_execute_advertiser(void)
{
int i,j;
int rc;
uint16_t handle;
uint16_t pktlen;
struct os_mbuf *om;
/* See if we should start advertising again */
if (g_bletest_current_conns < BLETEST_CFG_CONCURRENT_CONNS) {
handle = g_bletest_current_conns + 1;
if (ble_ll_conn_find_active_conn(handle)) {
/* Set LED to slower blink rate */
g_bletest_led_rate = OS_TICKS_PER_SEC;
/* advertising better be stopped! */
assert(ble_ll_adv_enabled() == 0);
/* Send the remote used features command */
rc = host_hci_cmd_le_read_rem_used_feat(handle);
host_hci_outstanding_opcode = 0;
if (rc) {
return;
}
/* Send the remote read version command */
rc = host_hci_cmd_rd_rem_version(handle);
host_hci_outstanding_opcode = 0;
if (rc) {
return;
}
/* set conn update time */
g_bletest_conn_upd_time = os_time_get() + (OS_TICKS_PER_SEC * 5);
g_bletest_start_update = 1;
/* Add to current connections */
++g_bletest_current_conns;
/* Move to next connection */
if (g_bletest_current_conns < BLETEST_CFG_CONCURRENT_CONNS) {
/* restart initiating */
g_bletest_cur_peer_addr[5] += 1;
g_dev_addr[5] += 1;
bletest_init_advertising();
rc = host_hci_cmd_le_set_adv_enable(1);
host_hci_outstanding_opcode = 0;
}
}
}
#if 0
if (g_bletest_start_update) {
if ((int32_t)(os_time_get() - g_bletest_conn_upd_time) >= 0) {
bletest_send_conn_update(1);
g_bletest_start_update = 0;
}
}
#endif
/* See if it is time to hand a data packet to the connection */
if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
if (g_bletest_current_conns) {
for (i = 0; i < g_bletest_current_conns; ++i) {
if ((g_last_handle_used == 0) ||
(g_last_handle_used > g_bletest_current_conns)) {
g_last_handle_used = 1;
}
handle = g_last_handle_used;
if (ble_ll_conn_find_active_conn(handle)) {
om = bletest_get_packet();
if (om) {
/* set payload length */
pktlen = BLETEST_PKT_SIZE;
om->om_len = BLETEST_PKT_SIZE + 4;
/* Put the HCI header in the mbuf */
htole16(om->om_data, handle);
htole16(om->om_data + 2, om->om_len);
/* Place L2CAP header in packet */
htole16(om->om_data + 4, pktlen);
om->om_data[6] = 0;
om->om_data[7] = 0;
/* Fill with incrementing pattern (starting from 1) */
for (j = 0; j < pktlen; ++j) {
om->om_data[8 + j] = (uint8_t)(j + 1);
}
/* Add length */
om->om_len += 4;
OS_MBUF_PKTHDR(om)->omp_len = om->om_len;
ble_hci_transport_host_acl_data_send(om);
/* Increment last handle used */
++g_last_handle_used;
}
} else {
++g_last_handle_used;
}
}
}
g_next_os_time = os_time_get() + OS_TICKS_PER_SEC;
}
}
#endif
#endif
/**
* Main bletest function. Called by the task timer every 50 msecs.
*
*/
void
bletest_execute(void)
{
/* Toggle LED at set rate */
if ((int32_t)(os_time_get() - g_bletest_next_led_time) >= 0) {
gpio_toggle(LED_BLINK_PIN);
g_bletest_next_led_time = os_time_get() + g_bletest_led_rate;
}
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER)
bletest_execute_advertiser();
#endif
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_SCANNER)
bletest_execute_scanner();
#endif
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_INITIATOR)
bletest_execute_initiator();
#endif
}
/**
* Callback when BLE test timer expires.
*
* @param arg
*/
void
bletest_timer_cb(void *arg)
{
/* Call the bletest code */
bletest_execute();
/* Re-start the timer (run every 50 msecs) */
os_callout_reset(&g_bletest_timer.cf_c, OS_TICKS_PER_SEC / 20);
}
/**
* BLE test task
*
* @param arg
*/
void
bletest_task_handler(void *arg)
{
int rc;
uint64_t event_mask;
struct os_event *ev;
struct os_callout_func *cf;
/* Set LED blink rate */
g_bletest_led_rate = OS_TICKS_PER_SEC / 20;
/* Wait one second before starting test task */
os_time_delay(OS_TICKS_PER_SEC);
/* Initialize eventq */
os_eventq_init(&g_bletest_evq);
/* Initialize the host timer */
os_callout_func_init(&g_bletest_timer, &g_bletest_evq, bletest_timer_cb,
NULL);
/* Send the reset command first */
rc = host_hci_cmd_send(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_RESET,
0, NULL);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER)
/* Initialize the advertiser */
console_printf("Starting BLE test task as advertiser\n");
bletest_init_advertising();
#endif
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_SCANNER)
/* Initialize the scanner */
console_printf("Starting BLE test task as scanner\n");
bletest_init_scanner();
#endif
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_INITIATOR)
/* Initialize the scanner */
console_printf("Starting BLE test task as initiator\n");
bletest_init_initiator();
#endif
/* Set the event mask we want to display */
event_mask = 0x7FF;
rc = host_hci_cmd_le_set_event_mask(event_mask);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
/* Turn on all events */
event_mask = 0xffffffffffffffff;
rc = host_hci_cmd_set_event_mask(event_mask);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
/* Turn on all events */
rc = host_hci_cmd_rd_local_version();
assert(rc == 0);
host_hci_outstanding_opcode = 0;
/* Wait some time before starting */
os_time_delay(OS_TICKS_PER_SEC);
/* Init bletest variables */
g_bletest_state = 0;
g_next_os_time = os_time_get();
/* Begin advertising if we are an advertiser */
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER)
rc = host_hci_cmd_le_set_adv_enable(1);
assert(rc == 0);
host_hci_outstanding_opcode = 0;
#endif
bletest_timer_cb(NULL);
while (1) {
ev = os_eventq_get(&g_bletest_evq);
switch (ev->ev_type) {
case OS_EVENT_T_TIMER:
cf = (struct os_callout_func *)ev;
assert(cf->cf_func);
cf->cf_func(cf->cf_arg);
break;
default:
assert(0);
break;
}
}
}
/**
* init_tasks
*
* Called by main.c after os_init(). This function performs initializations
* that are required before tasks are running.
*
* @return int 0 success; error otherwise.
*/
static int
init_tasks(void)
{
int rc;
os_task_init(&bletest_task, "bletest", bletest_task_handler, NULL,
BLETEST_TASK_PRIO, OS_WAIT_FOREVER, bletest_stack,
BLETEST_STACK_SIZE);
/* Initialize host HCI */
rc = ble_hs_init(HOST_TASK_PRIO, NULL);
assert(rc == 0);
/* Initialize the BLE LL */
ble_ll_init();
return 0;
}
/**
* main
*
* The main function for the project. This function initializes the os, calls
* init_tasks to initialize tasks (and possibly other objects), then starts the
* OS. We should not return from os start.
*
* @return int NOTE: this function should never return!
*/
int
main(void)
{
int i;
int rc;
uint32_t seed;
#if 0
int cnt;
struct nffs_area_desc descs[NFFS_AREA_MAX];
#endif
/* Initialize OS */
os_init();
/* Set cputime to count at 1 usec increments */
rc = cputime_init(1000000);
assert(rc == 0);
rc = os_mempool_init(&g_mbuf_mempool, MBUF_NUM_MBUFS,
MBUF_MEMBLOCK_SIZE, &g_mbuf_buffer[0], "mbuf_pool");
assert(rc == 0);
rc = os_mbuf_pool_init(&g_mbuf_pool, &g_mbuf_mempool, MBUF_MEMBLOCK_SIZE,
MBUF_NUM_MBUFS);
assert(rc == 0);
rc = os_msys_register(&g_mbuf_pool);
assert(rc == 0);
/* Dummy device address */
#if BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER
g_dev_addr[0] = 0x00;
g_dev_addr[1] = 0x00;
g_dev_addr[2] = 0x00;
g_dev_addr[3] = 0x88;
g_dev_addr[4] = 0x88;
g_dev_addr[5] = 0x08;
g_bletest_cur_peer_addr[0] = 0x00;
g_bletest_cur_peer_addr[1] = 0x00;
g_bletest_cur_peer_addr[2] = 0x00;
g_bletest_cur_peer_addr[3] = 0x99;
g_bletest_cur_peer_addr[4] = 0x99;
g_bletest_cur_peer_addr[5] = 0x09;
#else
g_dev_addr[0] = 0x00;
g_dev_addr[1] = 0x00;
g_dev_addr[2] = 0x00;
g_dev_addr[3] = 0x99;
g_dev_addr[4] = 0x99;
g_dev_addr[5] = 0x09;
g_bletest_cur_peer_addr[0] = 0x00;
g_bletest_cur_peer_addr[1] = 0x00;
g_bletest_cur_peer_addr[2] = 0x00;
g_bletest_cur_peer_addr[3] = 0x88;
g_bletest_cur_peer_addr[4] = 0x88;
g_bletest_cur_peer_addr[5] = 0x08;
#endif
/*
* Seed random number generator with least significant bytes of device
* address.
*/
seed = 0;
for (i = 0; i < 4; ++i) {
seed |= g_dev_addr[i];
seed <<= 8;
}
srand(seed);
/* Set the led pin as an output */
g_led_pin = LED_BLINK_PIN;
gpio_init_out(g_led_pin, 1);
/* Init the console */
rc = console_init(shell_console_rx_cb);
assert(rc == 0);
#if 0
rc = hal_flash_init();
assert(rc == 0);
nffs_config.nc_num_inodes = 32;
nffs_config.nc_num_blocks = 64;
nffs_config.nc_num_files = 2;
nffs_config.nc_num_dirs = 2;
rc = nffs_init();
assert(rc == 0);
cnt = NFFS_AREA_MAX;
rc = flash_area_to_nffs_desc(FLASH_AREA_NFFS, &cnt, descs);
assert(rc == 0);
if (nffs_detect(descs) == FS_ECORRUPT) {
rc = nffs_format(descs);
assert(rc == 0);
}
#endif
shell_task_init(SHELL_TASK_PRIO, shell_stack, SHELL_TASK_STACK_SIZE,
SHELL_MAX_INPUT_LEN);
nmgr_task_init(NEWTMGR_TASK_PRIO, newtmgr_stack, NEWTMGR_TASK_STACK_SIZE);
#if 0
imgmgr_module_init();
#endif
/* Init statistics module */
stats_module_init();
/* Init tasks */
init_tasks();
/* Start the OS */
os_start();
/* os start should never return. If it does, this should be an error */
assert(0);
return rc;
}