/******************************************************************************* * @file wfx_sl_ble_init.cpp * @brief ******************************************************************************* * # License * Copyright 2021 Silicon Laboratories Inc. www.silabs.com ******************************************************************************* * * Copyright (c) 2022 Project CHIP Authors * * Licensed 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 #include #include using namespace chip::DeviceLayer::Internal; // Global Variables SilabsBleWrapper::BleEvent_t bleEvent; /*==============================================*/ /** * @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 SilabsBleWrapper::rsi_ble_on_mtu_event(rsi_ble_event_mtu_t * rsi_ble_mtu) { bleEvent.eventType = BleEventType::RSI_BLE_MTU_EVENT; memcpy(&bleEvent.eventData->rsi_ble_mtu, rsi_ble_mtu, sizeof(rsi_ble_event_mtu_t)); BLEMgrImpl().BlePostEvent(&bleEvent); } /*==============================================*/ /** * @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 SilabsBleWrapper::rsi_ble_on_gatt_write_event(uint16_t event_id, rsi_ble_event_write_t * rsi_ble_write) { bleEvent.eventType = BleEventType::RSI_BLE_GATT_WRITE_EVENT; bleEvent.eventData->event_id = event_id; memcpy(&bleEvent.eventData->rsi_ble_write, rsi_ble_write, sizeof(rsi_ble_event_write_t)); BLEMgrImpl().BlePostEvent(&bleEvent); } /*==============================================*/ /** * @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 SilabsBleWrapper::rsi_ble_on_enhance_conn_status_event(rsi_ble_event_enhance_conn_status_t * resp_enh_conn) { bleEvent.eventType = BleEventType::RSI_BLE_CONN_EVENT; bleEvent.eventData->connectionHandle = 1; bleEvent.eventData->bondingHandle = 255; memcpy(bleEvent.eventData->resp_enh_conn.dev_addr, resp_enh_conn->dev_addr, RSI_DEV_ADDR_LEN); BLEMgrImpl().BlePostEvent(&bleEvent); } /*==============================================*/ /** * @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 SilabsBleWrapper::rsi_ble_on_disconnect_event(rsi_ble_event_disconnect_t * resp_disconnect, uint16_t reason) { bleEvent.eventType = BleEventType::RSI_BLE_DISCONN_EVENT; bleEvent.eventData->reason = reason; BLEMgrImpl().BlePostEvent(&bleEvent); } /*==============================================*/ /** * @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 SilabsBleWrapper::rsi_ble_on_event_indication_confirmation(uint16_t resp_status, rsi_ble_set_att_resp_t * rsi_ble_event_set_att_rsp) { bleEvent.eventType = BleEventType::RSI_BLE_GATT_INDICATION_CONFIRMATION; bleEvent.eventData->resp_status = resp_status; memcpy(&bleEvent.eventData->rsi_ble_event_set_att_rsp, rsi_ble_event_set_att_rsp, sizeof(rsi_ble_set_att_resp_t)); BLEMgrImpl().BlePostEvent(&bleEvent); } /*==============================================*/ /** * @fn rsi_ble_on_read_req_event * @brief its invoked when read events are received. * @param[in] event_id, it indicates write/notification event id. * @param[in] rsi_ble_read, read event parameters. * @return none. * @section description * This callback function is invoked when read events are received */ void SilabsBleWrapper::rsi_ble_on_read_req_event(uint16_t event_id, rsi_ble_read_req_t * rsi_ble_read_req) { bleEvent.eventType = BleEventType::RSI_BLE_EVENT_GATT_RD; bleEvent.eventData->event_id = event_id; memcpy(&bleEvent.eventData->rsi_ble_read_req, rsi_ble_read_req, sizeof(rsi_ble_read_req_t)); BLEMgrImpl().BlePostEvent(&bleEvent); } /*==============================================*/ /** * @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 SilabsBleWrapper::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 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 SilabsBleWrapper::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 SilabsBleWrapper::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 }; rsi_ble_t att_list; 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 SilabsBleWrapper::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[RSI_BLE_MATTER_CUSTOM_SERVICE_DATA_LENGTH] = { 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 }, .data2 = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_2 }, .data3 = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_3 }, .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 }, .data2 = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_2 }, .data3 = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_3 }, .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 bleEvent.eventData->rsi_ble_measurement_hndl = new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_MEASUREMENT_HANDLE_LOCATION; // Adding characteristic value attribute to the service bleEvent.eventData->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, bleEvent.eventData->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; }