/**************************************************************************** * apps/examples/nimble/nimble_main.c * * 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. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "netutils/netinit.h" #include "nimble/nimble_npl.h" #include "nimble/nimble_port.h" #include "host/ble_hs.h" #include "host/util/util.h" #include "services/gap/ble_svc_gap.h" #include "services/gatt/ble_svc_gatt.h" #include "services/ans/ble_svc_ans.h" #include "services/ias/ble_svc_ias.h" #include "services/lls/ble_svc_lls.h" #include "services/tps/ble_svc_tps.h" #include "services/gap/ble_svc_gap.h" #include "services/bas/ble_svc_bas.h" #include "services/dis/ble_svc_dis.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ /* Not used now */ #define TASK_DEFAULT_PRIORITY CONFIG_EXAMPLES_NIMBLE_PRIORITY #define TASK_DEFAULT_STACK NULL #define TASK_DEFAULT_STACK_SIZE 0 /**************************************************************************** * External Functions Prototypes ****************************************************************************/ void ble_hci_sock_ack_handler(FAR void *param); void ble_hci_sock_init(void); void ble_hci_sock_set_device(int dev); /**************************************************************************** * Private Functions Prototypes ****************************************************************************/ static void put_ad(uint8_t ad_type, uint8_t ad_len, FAR const void *ad, FAR uint8_t *buf, FAR uint8_t *len); static void update_ad(void); static void start_advertise(void); static int gap_event_cb(FAR struct ble_gap_event *event, FAR void *arg); static void app_ble_sync_cb(void); static void nimble_host_task(FAR void *param); static FAR void *ble_hci_sock_task(FAR void *param); static FAR void *ble_host_task(FAR void *param); /**************************************************************************** * Private Data ****************************************************************************/ static const char *g_gap_name = "NuttX NimBLE"; static uint8_t g_own_addr_type; /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: put_ad ****************************************************************************/ static void put_ad(uint8_t ad_type, uint8_t ad_len, FAR const void *ad, FAR uint8_t *buf, FAR uint8_t *len) { buf[(*len)++] = ad_len + 1; buf[(*len)++] = ad_type; memcpy(&buf[*len], ad, ad_len); *len += ad_len; } /**************************************************************************** * Name: update_ad ****************************************************************************/ static void update_ad(void) { uint8_t ad_flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP; uint8_t ad_len = 0; uint8_t ad[BLE_HS_ADV_MAX_SZ]; put_ad(BLE_HS_ADV_TYPE_FLAGS, 1, &ad_flags, ad, &ad_len); put_ad(BLE_HS_ADV_TYPE_COMP_NAME, sizeof(g_gap_name), g_gap_name, ad, &ad_len); ble_gap_adv_set_data(ad, ad_len); } /**************************************************************************** * Name: start_advertise ****************************************************************************/ static void start_advertise(void) { struct ble_gap_adv_params advp; int rc; printf("advertise\n"); update_ad(); memset(&advp, 0, sizeof advp); advp.conn_mode = BLE_GAP_CONN_MODE_UND; advp.disc_mode = BLE_GAP_DISC_MODE_GEN; rc = ble_gap_adv_start(g_own_addr_type, NULL, BLE_HS_FOREVER, &advp, gap_event_cb, NULL); assert(rc == 0); } /**************************************************************************** * Name: gap_event_cb ****************************************************************************/ static int gap_event_cb(FAR struct ble_gap_event *event, FAR void *arg) { switch (event->type) { case BLE_GAP_EVENT_CONNECT: { if (event->connect.status) { start_advertise(); } break; } case BLE_GAP_EVENT_DISCONNECT: { start_advertise(); break; } } return 0; } /**************************************************************************** * Name: app_ble_sync_cb ****************************************************************************/ static void app_ble_sync_cb(void) { ble_addr_t addr; int rc; /* Generate new non-resolvable private address */ rc = ble_hs_id_gen_rnd(1, &addr); assert(rc == 0); /* Set generated address */ rc = ble_hs_id_set_rnd(addr.val); assert(rc == 0); rc = ble_hs_util_ensure_addr(0); assert(rc == 0); rc = ble_hs_id_infer_auto(0, &g_own_addr_type); assert(rc == 0); start_advertise(); } /**************************************************************************** * Name: nimble_host_task ****************************************************************************/ static void nimble_host_task(FAR void *param) { ble_hs_cfg.sync_cb = app_ble_sync_cb; ble_svc_gap_device_name_set(g_gap_name); nimble_port_run(); } /**************************************************************************** * Name: ble_hci_sock_task ****************************************************************************/ static FAR void *ble_hci_sock_task(FAR void *param) { ble_hci_sock_ack_handler(param); return NULL; } /**************************************************************************** * Name: ble_host_task ****************************************************************************/ static FAR void *ble_host_task(FAR void *param) { nimble_host_task(param); return NULL; } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: nimble_main ****************************************************************************/ int main(int argc, FAR char *argv[]) { struct ble_npl_task s_task_host; struct ble_npl_task s_task_hci; uint8_t batt_level = 0; int ret = 0; /* allow to specify custom hci */ if (argc > 1) { ble_hci_sock_set_device(atoi(argv[1])); } #ifndef CONFIG_NSH_ARCHINIT /* Perform architecture-specific initialization */ boardctl(BOARDIOC_INIT, 0); #endif #ifndef CONFIG_NSH_NETINIT /* Bring up the network */ netinit_bringup(); #endif nimble_port_init(); ble_hci_sock_init(); /* Initialize services */ ble_svc_gap_init(); ble_svc_gatt_init(); ble_svc_ans_init(); ble_svc_ias_init(); ble_svc_lls_init(); ble_svc_tps_init(); ble_svc_bas_init(); ble_svc_dis_init(); /* Create task which handles HCI socket */ ret = ble_npl_task_init(&s_task_hci, "hci_sock", ble_hci_sock_task, NULL, TASK_DEFAULT_PRIORITY, BLE_NPL_TIME_FOREVER, TASK_DEFAULT_STACK, TASK_DEFAULT_STACK_SIZE); if (ret != 0) { printf("ERROR: starting hci task: %i\n", ret); } /* Create task which handles default event queue for host stack. */ ret = ble_npl_task_init(&s_task_host, "ble_host", ble_host_task, NULL, TASK_DEFAULT_PRIORITY, BLE_NPL_TIME_FOREVER, TASK_DEFAULT_STACK, TASK_DEFAULT_STACK_SIZE); if (ret != 0) { printf("ERROR: starting ble task: %i\n", ret); } while (true) { /* Simulate battery */ batt_level += 1; if (batt_level > 100) { batt_level = 0; } ble_svc_bas_battery_level_set(batt_level); sleep(1); } return 0; }