blob: 115e5c16ffdcec9ecea82aeeb2d69d4af621e199 [file] [log] [blame]
/*******************************************************************************
* @file wfx_sl_ble_init.c
* @brief
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
/*************************************************************************
*
*/
/*================================================================================
* @brief : This file contains example application for Wlan Station BLE
* Provisioning
* @section Description :
* This application explains how to get the WLAN connection functionality using
* BLE provisioning.
* Silicon Labs Module starts advertising and with BLE Provisioning the Access Point
* details are fetched.
* Silicon Labs device is configured as a WiFi station and connects to an Access Point.
=================================================================================*/
#include "wfx_sl_ble_init.h"
#include "rsi_ble_config.h"
// application defines
rsi_ble_event_conn_status_t conn_event_to_app;
rsi_ble_t att_list;
sl_wfx_msg_t event_msg;
// Memory to initialize driver
uint8_t bt_global_buf[BT_GLOBAL_BUFF_LEN];
static uint8_t wfx_rsi_drv_buf[WFX_RSI_BUF_SZ];
const uint8_t ShortUUID_CHIPoBLEService[] = { 0xF6, 0xFF };
/* Rsi driver Task will use as its stack */
// StackType_t driverRsiTaskStack[WFX_RSI_WLAN_TASK_SZ] = { 0 };
/* Structure that will hold the TCB of the wfxRsi Task being created. */
// StaticTask_t driverRsiTaskBuffer;
StaticTask_t rsiBLETaskStruct;
/* wfxRsi Task will use as its stack */
StackType_t wfxBLETaskStack[WFX_RSI_TASK_SZ] = { 0 };
int32_t ble_rsi_task(void)
{
int32_t status;
uint8_t buf[RSI_RESPONSE_HOLD_BUFF_SIZE];
// extern void rsi_hal_board_init(void);
//
// WFX_RSI_LOG("%s: starting(HEAP_SZ = %d)", __func__, SL_HEAP_SIZE);
//
// //! Driver initialization
// status = rsi_driver_init(wfx_rsi_drv_buf, WFX_RSI_BUF_SZ);
// if ((status < RSI_DRIVER_STATUS) || (status > WFX_RSI_BUF_SZ))
// {
// WFX_RSI_LOG("%s: error: RSI Driver initialization failed with status: %02x", __func__, status);
// return status;
// }
//
// WFX_RSI_LOG("%s: rsi_device_init", __func__);
//
// /* ! Redpine module intialisation */
// if ((status = rsi_device_init(LOAD_NWP_FW)) != RSI_SUCCESS)
// {
// WFX_RSI_LOG("%s: error: rsi_device_init failed with status: %02x", __func__, status);
// return status;
// }
// WFX_RSI_LOG("%s: start wireless drv task", __func__);
//
// /*
// * Create the driver task
// */
// wfx_rsi.drv_task = xTaskCreateStatic((TaskFunction_t) rsi_wireless_driver_task, "rsi_drv", WFX_RSI_WLAN_TASK_SZ, NULL,
// 1, driverRsiTaskStack, &driverRsiTaskBuffer);
// if (NULL == wfx_rsi.drv_task)
// {
// WFX_RSI_LOG("%s: error: Create the driver task failed", __func__);
// return RSI_ERROR_INVALID_PARAM;
// }
//
// /* Initialize WiSeConnect or Module features. */
// WFX_RSI_LOG("%s: rsi_wireless_init", __func__);
// if ((status = rsi_wireless_init(OPER_MODE_0, RSI_OPERMODE_WLAN_BLE)) != RSI_SUCCESS)
// {
// WFX_RSI_LOG("%s: error: Initialize WiSeConnect failed with status: %02x", __func__, status);
// return status;
// }
//
// WFX_RSI_LOG("%s: get FW version..", __func__);
//
// /*
// * Get the MAC and other info to let the user know about it.
// */
// if (rsi_wlan_get(RSI_FW_VERSION, buf, sizeof(buf)) != RSI_SUCCESS)
// {
// WFX_RSI_LOG("%s: error: rsi_wlan_get(RSI_FW_VERSION) failed with status: %02x", __func__, status);
// return status;
// }
//
// buf[sizeof(buf) - 1] = 0;
// WFX_RSI_LOG("%s: RSI firmware version: %s", __func__, buf);
// //! Send feature frame
// if ((status = rsi_send_feature_frame()) != RSI_SUCCESS)
// {
// WFX_RSI_LOG("%s: error: rsi_send_feature_frame failed with status: %02x", __func__, status);
// return status;
// }
//
// WFX_RSI_LOG("%s: sent rsi_send_feature_frame", __func__);
// /* initializes wlan radio parameters and WLAN supplicant parameters.
// */
// (void) rsi_wlan_radio_init(); /* Required so we can get MAC address */
// if ((status = rsi_wlan_get(RSI_MAC_ADDRESS, &wfx_rsi.sta_mac.octet[0], RESP_BUFF_SIZE)) != RSI_SUCCESS)
// {
// WFX_RSI_LOG("%s: error: rsi_wlan_get failed with status: %02x", __func__, status);
// return status;
// }
// registering the GAP callback functions
rsi_ble_gap_register_callbacks(NULL, NULL, rsi_ble_on_disconnect_event, NULL, NULL, NULL, rsi_ble_on_enhance_conn_status_event,
NULL, NULL, NULL);
// registering the GATT call back functions
rsi_ble_gatt_register_callbacks(NULL, NULL, NULL, NULL, NULL, NULL, NULL, rsi_ble_on_gatt_write_event, NULL, NULL, NULL,
rsi_ble_on_mtu_event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
rsi_ble_on_event_indication_confirmation, NULL);
WFX_RSI_LOG("registering rsi_ble_add_service");
// Exchange of GATT info with BLE stack
rsi_ble_add_matter_service();
// initializing the application events map
rsi_ble_app_init_events();
wfx_rsi.ble_task = xTaskCreateStatic((TaskFunction_t) rsi_ble_event_handling_task, "rsi_ble", WFX_RSI_TASK_SZ, NULL, 2,
wfxBLETaskStack, &rsiBLETaskStruct);
WFX_RSI_LOG("%s: rsi_task_suspend init_task ", __func__);
if (wfx_rsi.ble_task == NULL)
{
WFX_RSI_LOG("%s: error: failed to create ble task.", __func__);
}
WFX_RSI_LOG("%s complete", __func__);
// rsi_task_destroy((rsi_task_handle_t *)wfx_rsi.init_task);
return RSI_SUCCESS;
}
/*==============================================*/
/**
* @fn rsi_ble_app_init_events
* @brief initializes the event parameter.
* @param[in] none.
* @return none.
* @section description
* This function is used during BLE initialization.
*/
void rsi_ble_app_init_events()
{
event_msg.ble_app_event_map = 0;
event_msg.ble_app_event_mask = 0xFFFFFFFF;
event_msg.ble_app_event_mask = event_msg.ble_app_event_mask; // To suppress warning while compiling
WFX_RSI_LOG("Function :: rsi_ble_app_init_events");
return;
}
/*==============================================*/
/**
* @fn rsi_ble_app_clear_event
* @brief clears the specific event.
* @param[in] event_num, specific event number.
* @return none.
* @section description
* This function is used to clear the specific event.
*/
void rsi_ble_app_clear_event(uint32_t event_num)
{
event_msg.event_num = event_num;
event_msg.ble_app_event_map &= ~BIT(event_num);
return;
}
/*==============================================*/
/**
* @fn rsi_ble_on_mtu_event
* @brief its invoked when mtu exhange event is received.
* @param[in] rsi_ble_mtu, mtu event paramaters.
* @return none.
* @section description
* This callback function is invoked when mtu exhange event is received
*/
void rsi_ble_on_mtu_event(rsi_ble_event_mtu_t * rsi_ble_mtu)
{
WFX_RSI_LOG(" RSI_BLE : rsi_ble_on_mtu_event");
memset(&event_msg.rsi_ble_mtu, 0, sizeof(rsi_ble_event_mtu_t));
memcpy(&event_msg.rsi_ble_mtu, rsi_ble_mtu, sizeof(rsi_ble_event_mtu_t));
rsi_ble_app_set_event(RSI_BLE_MTU_EVENT);
}
/*==============================================*/
/**
* @fn rsi_ble_on_gatt_write_event
* @brief its invoked when write/notify/indication events are received.
* @param[in] event_id, it indicates write/notification event id.
* @param[in] rsi_ble_write, write event parameters.
* @return none.
* @section description
* This callback function is invoked when write/notify/indication events are received
*/
void rsi_ble_on_gatt_write_event(uint16_t event_id, rsi_ble_event_write_t * rsi_ble_write)
{
WFX_RSI_LOG(" RSI_BLE : rsi_ble_on_gatt_write_event");
memset(&event_msg.rsi_ble_write, 0, sizeof(rsi_ble_event_write_t));
event_msg.event_id = event_id;
memcpy(&event_msg.rsi_ble_write, rsi_ble_write, sizeof(rsi_ble_event_write_t));
rsi_ble_app_set_event(RSI_BLE_GATT_WRITE_EVENT);
}
/*==============================================*/
/**
* @fn rsi_ble_on_enhance_conn_status_event
* @brief invoked when enhanced connection complete event is received
* @param[out] resp_conn, connected remote device information
* @return none.
* @section description
* This callback function indicates the status of the connection
*/
void rsi_ble_on_enhance_conn_status_event(rsi_ble_event_enhance_conn_status_t * resp_enh_conn)
{
WFX_RSI_LOG(" RSI_BLE : rsi_ble_on_enhance_conn_status_event");
event_msg.connectionHandle = 1;
event_msg.bondingHandle = 255;
memcpy(event_msg.resp_enh_conn.dev_addr, resp_enh_conn->dev_addr, RSI_DEV_ADDR_LEN);
rsi_ble_app_set_event(RSI_BLE_CONN_EVENT);
}
/*==============================================*/
/**
* @fn rsi_ble_on_disconnect_event
* @brief invoked when disconnection event is received
* @param[in] resp_disconnect, disconnected remote device information
* @param[in] reason, reason for disconnection.
* @return none.
* @section description
* This callback function indicates disconnected device information and status
*/
void rsi_ble_on_disconnect_event(rsi_ble_event_disconnect_t * resp_disconnect, uint16_t reason)
{
WFX_RSI_LOG(" RSI_BLE : rsi_ble_on_disconnect_event");
event_msg.reason = reason;
memcpy(event_msg.resp_disconnect, resp_disconnect, sizeof(rsi_ble_event_disconnect_t));
rsi_ble_app_set_event(RSI_BLE_DISCONN_EVENT);
}
/*==============================================*/
/**
* @fn rsi_ble_on_event_indication_confirmation
* @brief this function will invoke when received indication confirmation event
* @param[out] resp_id, response id
* @param[out] status, status of the response
* @return none
* @section description
*/
void rsi_ble_on_event_indication_confirmation(uint16_t resp_status, rsi_ble_set_att_resp_t * rsi_ble_event_set_att_rsp)
{
WFX_RSI_LOG(" RSI_BLE : rsi_ble_on_event_indication_confirmation");
event_msg.resp_status = resp_status;
memcpy(&event_msg.rsi_ble_event_set_att_rsp, rsi_ble_event_set_att_rsp, sizeof(rsi_ble_set_att_resp_t));
rsi_ble_app_set_event(RSI_BLE_GATT_INDICATION_CONFIRMATION);
}
/*==============================================*/
/**
* @fn rsi_ble_app_get_event
* @brief returns the first set event based on priority
* @param[in] none.
* @return int32_t
* > 0 = event number
* -1 = not received any event
* @section description
* This function returns the highest priority event among all the set events
*/
int32_t rsi_ble_app_get_event(void)
{
uint32_t ix;
for (ix = 0; ix < 32; ix++)
{
if (event_msg.ble_app_event_map & (1 << ix))
{
return ix;
}
}
return (-1);
}
/*==============================================*/
/**
* @fn rsi_ble_app_set_event
* @brief set the specific event.
* @param[in] event_num, specific event number.
* @return none.
* @section description
* This function is used to set/raise the specific event.
*/
void rsi_ble_app_set_event(uint32_t event_num)
{
event_msg.ble_app_event_map |= BIT(event_num);
return;
}
/*==============================================*/
/**
* @fn rsi_gatt_add_attribute_to_list
* @brief This function is used to store characteristic service attribute.
* @param[in] p_val, pointer to homekit structure
* @param[in] handle, characteristic service attribute handle.
* @param[in] data_len, characteristic value length
* @param[in] data, characteristic value pointer
* @param[in] uuid, characteristic value uuid
* @return none.
* @section description
* This function is used to store all attribute records
*/
void rsi_gatt_add_attribute_to_list(rsi_ble_t * p_val, uint16_t handle, uint16_t data_len, uint8_t * data, uuid_t uuid,
uint8_t char_prop)
{
if ((p_val->DATA_ix + data_len) >= BLE_ATT_REC_SIZE)
{ //! Check for max data length for the characteristic value
LOG_PRINT("\r\n no data memory for att rec values \r\n");
return;
}
p_val->att_rec_list[p_val->att_rec_list_count].char_uuid = uuid;
p_val->att_rec_list[p_val->att_rec_list_count].handle = handle;
p_val->att_rec_list[p_val->att_rec_list_count].value_len = data_len;
p_val->att_rec_list[p_val->att_rec_list_count].max_value_len = data_len;
p_val->att_rec_list[p_val->att_rec_list_count].char_val_prop = char_prop;
memcpy(p_val->DATA + p_val->DATA_ix, data, data_len);
p_val->att_rec_list[p_val->att_rec_list_count].value = p_val->DATA + p_val->DATA_ix;
p_val->att_rec_list_count++;
p_val->DATA_ix += p_val->att_rec_list[p_val->att_rec_list_count].max_value_len;
return;
}
/*==============================================*/
/**
* @fn rsi_ble_add_char_serv_att
* @brief this function is used to add characteristic service attribute..
* @param[in] serv_handler, service handler.
* @param[in] handle, characteristic service attribute handle.
* @param[in] val_prop, characteristic value property.
* @param[in] att_val_handle, characteristic value handle
* @param[in] att_val_uuid, characteristic value uuid
* @return none.
* @section description
* This function is used at application to add characteristic attribute
*/
void rsi_ble_add_char_serv_att(void * serv_handler, uint16_t handle, uint8_t val_prop, uint16_t att_val_handle, uuid_t att_val_uuid)
{
rsi_ble_req_add_att_t new_att = { 0 };
//! preparing the attribute service structure
new_att.serv_handler = serv_handler;
new_att.handle = handle;
new_att.att_uuid.size = 2;
new_att.att_uuid.val.val16 = RSI_BLE_CHAR_SERV_UUID;
new_att.property = RSI_BLE_ATT_PROPERTY_READ;
//! preparing the characteristic attribute value
new_att.data_len = att_val_uuid.size + 4;
new_att.data[0] = val_prop;
rsi_uint16_to_2bytes(&new_att.data[2], att_val_handle);
if (new_att.data_len == 6)
{
rsi_uint16_to_2bytes(&new_att.data[4], att_val_uuid.val.val16);
}
else if (new_att.data_len == 8)
{
rsi_uint32_to_4bytes(&new_att.data[4], att_val_uuid.val.val32);
}
else if (new_att.data_len == 20)
{
memcpy(&new_att.data[4], &att_val_uuid.val.val128, att_val_uuid.size);
}
//! Add attribute to the service
rsi_ble_add_attribute(&new_att);
return;
}
/*==============================================*/
/**
* @fn rsi_ble_add_char_val_att
* @brief this function is used to add characteristic value attribute.
* @param[in] serv_handler, new service handler.
* @param[in] handle, characteristic value attribute handle.
* @param[in] att_type_uuid, attribute uuid value.
* @param[in] val_prop, characteristic value property.
* @param[in] data, characteristic value data pointer.
* @param[in] data_len, characteristic value length.
* @return none.
* @section description
* This function is used at application to create new service.
*/
void rsi_ble_add_char_val_att(void * serv_handler, uint16_t handle, uuid_t att_type_uuid, uint8_t val_prop, uint8_t * data,
uint8_t data_len, uint8_t auth_read)
{
rsi_ble_req_add_att_t new_att = { 0 };
memset(&new_att, 0, sizeof(rsi_ble_req_add_att_t));
//! preparing the attributes
new_att.serv_handler = serv_handler;
new_att.handle = handle;
new_att.config_bitmap = auth_read;
memcpy(&new_att.att_uuid, &att_type_uuid, sizeof(uuid_t));
new_att.property = val_prop;
if (data != NULL)
memcpy(new_att.data, data, RSI_MIN(sizeof(new_att.data), data_len));
//! preparing the attribute value
new_att.data_len = data_len;
//! add attribute to the service
rsi_ble_add_attribute(&new_att);
if ((auth_read == ATT_REC_MAINTAIN_IN_HOST) || (data_len > 20))
{
if (data != NULL)
{
rsi_gatt_add_attribute_to_list(&att_list, handle, data_len, data, att_type_uuid, val_prop);
}
}
//! check the attribute property with notification/Indication
if ((val_prop & RSI_BLE_ATT_PROPERTY_NOTIFY) || (val_prop & RSI_BLE_ATT_PROPERTY_INDICATE))
{
//! if notification/indication property supports then we need to add client characteristic service.
//! preparing the client characteristic attribute & values
memset(&new_att, 0, sizeof(rsi_ble_req_add_att_t));
new_att.serv_handler = serv_handler;
new_att.handle = handle + 1;
new_att.att_uuid.size = 2;
new_att.att_uuid.val.val16 = RSI_BLE_CLIENT_CHAR_UUID;
new_att.property = RSI_BLE_ATT_PROPERTY_READ | RSI_BLE_ATT_PROPERTY_WRITE;
new_att.data_len = 2;
//! add attribute to the service
rsi_ble_add_attribute(&new_att);
}
return;
}
/*==============================================*/
/**
* @fn rsi_ble_add_matter_service
* @brief this function is used to add service for matter
* @return status (uint32_t) 0 for success.
* @section description
* This function is used at application to create new service.
*/
uint32_t rsi_ble_add_matter_service(void)
{
uuid_t custom_service = { RSI_BLE_MATTER_CUSTOM_SERVICE_UUID };
custom_service.size = RSI_BLE_MATTER_CUSTOM_SERVICE_SIZE;
custom_service.val.val16 = RSI_BLE_MATTER_CUSTOM_SERVICE_VALUE_16;
uint8_t data[230] = { RSI_BLE_MATTER_CUSTOM_SERVICE_DATA };
static const uuid_t custom_characteristic_RX = { .size = RSI_BLE_CUSTOM_CHARACTERISTIC_RX_SIZE,
.reserved = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_RESERVED },
.val.val128.data1 = RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_1,
.val.val128.data2 = RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_2,
.val.val128.data3 = RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_3,
.val.val128.data4 = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_4 } };
rsi_ble_resp_add_serv_t new_serv_resp = { 0 };
rsi_ble_add_service(custom_service, &new_serv_resp);
// Adding custom characteristic declaration to the custom service
rsi_ble_add_char_serv_att(
new_serv_resp.serv_handler, new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_RX_ATTRIBUTE_HANDLE_LOCATION,
RSI_BLE_ATT_PROPERTY_WRITE | RSI_BLE_ATT_PROPERTY_READ, // Set read, write, write without response
new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_RX_VALUE_HANDLE_LOCATION, custom_characteristic_RX);
// Adding characteristic value attribute to the service
rsi_ble_add_char_val_att(new_serv_resp.serv_handler,
new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_RX_VALUE_HANDLE_LOCATION, custom_characteristic_RX,
RSI_BLE_ATT_PROPERTY_WRITE | RSI_BLE_ATT_PROPERTY_READ, // Set read, write, write without response
data, sizeof(data), ATT_REC_IN_HOST);
static const uuid_t custom_characteristic_TX = { .size = RSI_BLE_CUSTOM_CHARACTERISTIC_TX_SIZE,
.reserved = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_RESERVED },
.val.val128.data1 = RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_1,
.val.val128.data2 = RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_2,
.val.val128.data3 = RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_3,
.val.val128.data4 = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_4 } };
// Adding custom characteristic declaration to the custom service
rsi_ble_add_char_serv_att(
new_serv_resp.serv_handler, new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_ATTRIBUTE_HANDLE_LOCATION,
RSI_BLE_ATT_PROPERTY_WRITE_NO_RESPONSE | RSI_BLE_ATT_PROPERTY_WRITE | RSI_BLE_ATT_PROPERTY_READ |
RSI_BLE_ATT_PROPERTY_NOTIFY | RSI_BLE_ATT_PROPERTY_INDICATE, // Set read, write, write without response
new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_MEASUREMENT_HANDLE_LOCATION, custom_characteristic_TX);
// Adding characteristic value attribute to the service
event_msg.rsi_ble_measurement_hndl = new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_MEASUREMENT_HANDLE_LOCATION;
// Adding characteristic value attribute to the service
event_msg.rsi_ble_gatt_server_client_config_hndl =
new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_GATT_SERVER_CLIENT_HANDLE_LOCATION;
rsi_ble_add_char_val_att(new_serv_resp.serv_handler, event_msg.rsi_ble_measurement_hndl, custom_characteristic_TX,
RSI_BLE_ATT_PROPERTY_WRITE_NO_RESPONSE | RSI_BLE_ATT_PROPERTY_WRITE | RSI_BLE_ATT_PROPERTY_READ |
RSI_BLE_ATT_PROPERTY_NOTIFY |
RSI_BLE_ATT_PROPERTY_INDICATE, // Set read, write, write without response
data, sizeof(data), ATT_REC_MAINTAIN_IN_HOST);
memset(&data, 0, sizeof(data));
return 0;
}