Loading system/bta/ras/ras_server.cc +147 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ class RasServerImpl : public bluetooth::ras::RasServer { uint16_t conn_id_; std::unordered_map<Uuid, uint16_t> ccc_values_; std::vector<DataBuffer> buffers_; bool handling_control_point_command_ = false; }; void Initialize() { Loading Loading @@ -154,6 +155,9 @@ class RasServerImpl : public bluetooth::ras::RasServer { case BTA_GATTS_READ_DESCRIPTOR_EVT: { OnReadDescriptor(p_data); } break; case BTA_GATTS_WRITE_CHARACTERISTIC_EVT: { OnWriteCharacteristic(p_data); } break; case BTA_GATTS_WRITE_DESCRIPTOR_EVT: { OnWriteDescriptor(p_data); } break; Loading Loading @@ -335,6 +339,54 @@ class RasServerImpl : public bluetooth::ras::RasServer { BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_SUCCESS, &p_msg); } void OnWriteCharacteristic(tBTA_GATTS* p_data) { uint16_t conn_id = p_data->req_data.conn_id; uint16_t write_req_handle = p_data->req_data.p_data->write_req.handle; uint16_t len = p_data->req_data.p_data->write_req.len; log::info("conn_id:{}, write_req_handle:{}, len:{}", conn_id, write_req_handle, len); tGATTS_RSP p_msg; p_msg.handle = write_req_handle; if (characteristics_.find(write_req_handle) == characteristics_.end()) { log::error("Invalid handle {}", write_req_handle); BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id, GATT_INVALID_HANDLE, &p_msg); return; } auto uuid = characteristics_[write_req_handle].uuid_; log::info("Write uuid, {}", getUuidName(uuid)); // Check Characteristic UUID switch (uuid.As16Bit()) { case kRasControlPointCharacteristic16bit: { if (trackers_.find(p_data->req_data.remote_bda) == trackers_.end()) { log::warn("Can't find trackers for {}", ADDRESS_TO_LOGGABLE_STR(p_data->req_data.remote_bda)); BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_ILLEGAL_PARAMETER, &p_msg); return; } ClientTracker* tracker = &trackers_[p_data->req_data.remote_bda]; if (tracker->handling_control_point_command_) { log::warn("Procedure Already In Progress"); BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_PRC_IN_PROGRESS, &p_msg); return; } BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_SUCCESS, &p_msg); HandleControlPoint(tracker, &p_data->req_data.p_data->write_req); } break; default: log::warn("Unhandled uuid {}", uuid.ToString()); BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id, GATT_ILLEGAL_PARAMETER, &p_msg); return; } } void OnWriteDescriptor(tBTA_GATTS* p_data) { uint16_t conn_id = p_data->req_data.conn_id; uint16_t write_req_handle = p_data->req_data.p_data->write_req.handle; Loading Loading @@ -367,6 +419,101 @@ class RasServerImpl : public bluetooth::ras::RasServer { BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_SUCCESS, &p_msg); } void HandleControlPoint(ClientTracker* tracker, tGATT_WRITE_REQ* write_req) { ControlPointCommand command; if (!ParseControlPointCommand(&command, write_req->value, write_req->len)) { return; } tracker->handling_control_point_command_ = true; switch (command.opcode_) { case Opcode::GET_RANGING_DATA: { OnGetRangingData(&command, tracker); } break; case Opcode::ACK_RANGING_DATA: { OnAckRangingData(&command, tracker); } break; default: LOG_WARN("Unknown opcode:0x%02x", (uint16_t)command.opcode_); } } void OnGetRangingData(ControlPointCommand* command, ClientTracker* tracker) { const uint8_t* value = command->operand_; uint16_t ranging_counter; STREAM_TO_UINT16(ranging_counter, value); log::info("ranging_counter:{}", ranging_counter); uint16_t ccc_value = tracker->ccc_values_[kRasOnDemandDataCharacteristic]; uint16_t attr_id = GetCharacteristic(kRasOnDemandDataCharacteristic)->attribute_handle_; bool need_confirm = ccc_value & GATT_CLT_CONFIG_INDICATION; std::lock_guard<std::mutex> lock(data_mutex_); auto it = std::find_if(tracker->buffers_.begin(), tracker->buffers_.end(), [&ranging_counter](const DataBuffer& buffer) { return buffer.ranging_counter_ == ranging_counter; }); if (it != tracker->buffers_.end()) { for (uint16_t i = 0; i < it->segments_.size(); i++) { if (ccc_value == GATT_CLT_CONFIG_NONE) { log::warn("On Demand Data is not subscribed, Skip"); break; } log::info("Send On Demand Ranging Data, segment {}", i); BTA_GATTS_HandleValueIndication(tracker->conn_id_, attr_id, it->segments_[i], need_confirm); } log::info("Send COMPLETE_RANGING_DATA_RESPONSE, ranging_counter:{}", ranging_counter); std::vector<uint8_t> response(8, 0); response[0] = (uint8_t)EventCode::COMPLETE_RANGING_DATA_RESPONSE; response[1] = 0; // Null response[2] = (ranging_counter & 0xFF); response[3] = (ranging_counter >> 8) & 0xFF; BTA_GATTS_HandleValueIndication( tracker->conn_id_, GetCharacteristic(kRasControlPointCharacteristic)->attribute_handle_, response, true); tracker->handling_control_point_command_ = false; return; } }; void OnAckRangingData(ControlPointCommand* command, ClientTracker* tracker) { const uint8_t* value = command->operand_; uint16_t ranging_counter; STREAM_TO_UINT16(ranging_counter, value); log::info("ranging_counter:{}", ranging_counter); std::lock_guard<std::mutex> lock(data_mutex_); auto it = std::find_if(tracker->buffers_.begin(), tracker->buffers_.end(), [&ranging_counter](const DataBuffer& buffer) { return buffer.ranging_counter_ == ranging_counter; }); // If found, erase it if (it != tracker->buffers_.end()) { tracker->buffers_.erase(it); tracker->handling_control_point_command_ = false; } }; void SendResponseCode(ResponseCodeValue response_code_value, ClientTracker* tracker) { log::info("0x{:02x}, {}", (uint16_t)response_code_value, GetResponseOpcodeValueText(response_code_value)); std::vector<uint8_t> response(8, 0); response[0] = (uint8_t)EventCode::RESPONSE_CODE; response[1] = 0; // Null response[2] = (uint8_t)response_code_value; BTA_GATTS_HandleValueIndication( tracker->conn_id_, GetCharacteristic(kRasControlPointCharacteristic)->attribute_handle_, response, true); tracker->handling_control_point_command_ = false; } void OnServiceAdded(tGATT_STATUS status, int server_if, std::vector<btgatt_db_element_t> service) { log::info("status: {}, server_if: {}", gatt_status_text(status), server_if); Loading system/bta/ras/ras_types.h +49 −0 Original line number Diff line number Diff line Loading @@ -63,4 +63,53 @@ static const uint32_t kFilterRangingData = 0x08; static const uint32_t kPctPhaseFormat = 0xA0; } // namespace feature enum class Opcode : uint8_t { GET_RANGING_DATA = 0x00, ACK_RANGING_DATA = 0x01, RETRIEVE_LOST_RANGING_DATA_SEGMENTS = 0x02, ABORT_OPERATION = 0x03, FILTER = 0x04, PCT_FORMAT = 0x05, }; static const uint8_t OPERATOR_NULL = 0x00; std::string GetOpcodeText(Opcode opcode); enum class EventCode : uint8_t { COMPLETE_RANGING_DATA_RESPONSE = 0x00, COMPLETE_LOST_RANGING_DATA_SEGMENT_RESPONSE = 0x01, RESPONSE_CODE = 0x02, }; enum class ResponseCodeValue : uint8_t { RESERVED_FOR_FUTURE_USE = 0x00, SUCCESS = 0x01, OP_CODE_NOT_SUPPORTED = 0x02, INVALID_OPERATOR = 0x03, OPERATOR_NOT_SUPPORTED = 0x04, INVALID_OPERAND = 0x05, ABORT_UNSUCCESSFUL = 0x06, PROCEDURE_NOT_COMPLETED = 0x07, OPERAND_NOT_SUPPORTED = 0x08, NO_RECORDS_FOUND = 0x09, }; std::string GetResponseOpcodeValueText(ResponseCodeValue response_code_value); struct ControlPointCommand { Opcode opcode_; uint8_t operator_; uint8_t operand_[6]; }; struct ControlPointResponse { EventCode event_code_; uint8_t operator_; uint8_t operand_[6]; }; bool ParseControlPointCommand(ControlPointCommand* command, const uint8_t* value, uint16_t len); } // namespace ras system/bta/ras/ras_utils.cc +59 −0 Original line number Diff line number Diff line Loading @@ -55,4 +55,63 @@ std::string uuid::getUuidName(const bluetooth::Uuid& uuid) { } } bool ParseControlPointCommand(ControlPointCommand* command, const uint8_t* value, uint16_t len) { // Check for minimum expected length if (len != kControlPointCommandSize) { LOG_WARN("Invalid len %d", len); return false; } command->opcode_ = static_cast<Opcode>(value[0]); command->operator_ = value[1]; std::memcpy(command->operand_, value + 2, 6); return true; } std::string GetOpcodeText(Opcode opcode) { switch (opcode) { case Opcode::GET_RANGING_DATA: return "GET_RANGING_DATA"; case Opcode::ACK_RANGING_DATA: return "ACK_RANGING_DATA"; case Opcode::RETRIEVE_LOST_RANGING_DATA_SEGMENTS: return "RETRIEVE_LOST_RANGING_DATA_SEGMENTS"; case Opcode::ABORT_OPERATION: return "ABORT_OPERATION"; case Opcode::FILTER: return "FILTER"; case Opcode::PCT_FORMAT: return "PCT_FORMAT"; default: return "Unknown Opcode"; } } std::string GetResponseOpcodeValueText(ResponseCodeValue response_code_value) { switch (response_code_value) { case ResponseCodeValue::RESERVED_FOR_FUTURE_USE: return "RESERVED_FOR_FUTURE_USE"; case ResponseCodeValue::SUCCESS: return "SUCCESS"; case ResponseCodeValue::OP_CODE_NOT_SUPPORTED: return "OP_CODE_NOT_SUPPORTED"; case ResponseCodeValue::INVALID_OPERATOR: return "INVALID_OPERATOR"; case ResponseCodeValue::OPERATOR_NOT_SUPPORTED: return "OPERATOR_NOT_SUPPORTED"; case ResponseCodeValue::INVALID_OPERAND: return "INVALID_OPERAND"; case ResponseCodeValue::ABORT_UNSUCCESSFUL: return "ABORT_UNSUCCESSFUL"; case ResponseCodeValue::PROCEDURE_NOT_COMPLETED: return "PROCEDURE_NOT_COMPLETED"; case ResponseCodeValue::OPERAND_NOT_SUPPORTED: return "OPERAND_NOT_SUPPORTED"; case ResponseCodeValue::NO_RECORDS_FOUND: return "NO_RECORDS_FOUND"; default: return "Unknown Opcode"; } } } // namespace ras Loading
system/bta/ras/ras_server.cc +147 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ class RasServerImpl : public bluetooth::ras::RasServer { uint16_t conn_id_; std::unordered_map<Uuid, uint16_t> ccc_values_; std::vector<DataBuffer> buffers_; bool handling_control_point_command_ = false; }; void Initialize() { Loading Loading @@ -154,6 +155,9 @@ class RasServerImpl : public bluetooth::ras::RasServer { case BTA_GATTS_READ_DESCRIPTOR_EVT: { OnReadDescriptor(p_data); } break; case BTA_GATTS_WRITE_CHARACTERISTIC_EVT: { OnWriteCharacteristic(p_data); } break; case BTA_GATTS_WRITE_DESCRIPTOR_EVT: { OnWriteDescriptor(p_data); } break; Loading Loading @@ -335,6 +339,54 @@ class RasServerImpl : public bluetooth::ras::RasServer { BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_SUCCESS, &p_msg); } void OnWriteCharacteristic(tBTA_GATTS* p_data) { uint16_t conn_id = p_data->req_data.conn_id; uint16_t write_req_handle = p_data->req_data.p_data->write_req.handle; uint16_t len = p_data->req_data.p_data->write_req.len; log::info("conn_id:{}, write_req_handle:{}, len:{}", conn_id, write_req_handle, len); tGATTS_RSP p_msg; p_msg.handle = write_req_handle; if (characteristics_.find(write_req_handle) == characteristics_.end()) { log::error("Invalid handle {}", write_req_handle); BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id, GATT_INVALID_HANDLE, &p_msg); return; } auto uuid = characteristics_[write_req_handle].uuid_; log::info("Write uuid, {}", getUuidName(uuid)); // Check Characteristic UUID switch (uuid.As16Bit()) { case kRasControlPointCharacteristic16bit: { if (trackers_.find(p_data->req_data.remote_bda) == trackers_.end()) { log::warn("Can't find trackers for {}", ADDRESS_TO_LOGGABLE_STR(p_data->req_data.remote_bda)); BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_ILLEGAL_PARAMETER, &p_msg); return; } ClientTracker* tracker = &trackers_[p_data->req_data.remote_bda]; if (tracker->handling_control_point_command_) { log::warn("Procedure Already In Progress"); BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_PRC_IN_PROGRESS, &p_msg); return; } BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_SUCCESS, &p_msg); HandleControlPoint(tracker, &p_data->req_data.p_data->write_req); } break; default: log::warn("Unhandled uuid {}", uuid.ToString()); BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id, GATT_ILLEGAL_PARAMETER, &p_msg); return; } } void OnWriteDescriptor(tBTA_GATTS* p_data) { uint16_t conn_id = p_data->req_data.conn_id; uint16_t write_req_handle = p_data->req_data.p_data->write_req.handle; Loading Loading @@ -367,6 +419,101 @@ class RasServerImpl : public bluetooth::ras::RasServer { BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_SUCCESS, &p_msg); } void HandleControlPoint(ClientTracker* tracker, tGATT_WRITE_REQ* write_req) { ControlPointCommand command; if (!ParseControlPointCommand(&command, write_req->value, write_req->len)) { return; } tracker->handling_control_point_command_ = true; switch (command.opcode_) { case Opcode::GET_RANGING_DATA: { OnGetRangingData(&command, tracker); } break; case Opcode::ACK_RANGING_DATA: { OnAckRangingData(&command, tracker); } break; default: LOG_WARN("Unknown opcode:0x%02x", (uint16_t)command.opcode_); } } void OnGetRangingData(ControlPointCommand* command, ClientTracker* tracker) { const uint8_t* value = command->operand_; uint16_t ranging_counter; STREAM_TO_UINT16(ranging_counter, value); log::info("ranging_counter:{}", ranging_counter); uint16_t ccc_value = tracker->ccc_values_[kRasOnDemandDataCharacteristic]; uint16_t attr_id = GetCharacteristic(kRasOnDemandDataCharacteristic)->attribute_handle_; bool need_confirm = ccc_value & GATT_CLT_CONFIG_INDICATION; std::lock_guard<std::mutex> lock(data_mutex_); auto it = std::find_if(tracker->buffers_.begin(), tracker->buffers_.end(), [&ranging_counter](const DataBuffer& buffer) { return buffer.ranging_counter_ == ranging_counter; }); if (it != tracker->buffers_.end()) { for (uint16_t i = 0; i < it->segments_.size(); i++) { if (ccc_value == GATT_CLT_CONFIG_NONE) { log::warn("On Demand Data is not subscribed, Skip"); break; } log::info("Send On Demand Ranging Data, segment {}", i); BTA_GATTS_HandleValueIndication(tracker->conn_id_, attr_id, it->segments_[i], need_confirm); } log::info("Send COMPLETE_RANGING_DATA_RESPONSE, ranging_counter:{}", ranging_counter); std::vector<uint8_t> response(8, 0); response[0] = (uint8_t)EventCode::COMPLETE_RANGING_DATA_RESPONSE; response[1] = 0; // Null response[2] = (ranging_counter & 0xFF); response[3] = (ranging_counter >> 8) & 0xFF; BTA_GATTS_HandleValueIndication( tracker->conn_id_, GetCharacteristic(kRasControlPointCharacteristic)->attribute_handle_, response, true); tracker->handling_control_point_command_ = false; return; } }; void OnAckRangingData(ControlPointCommand* command, ClientTracker* tracker) { const uint8_t* value = command->operand_; uint16_t ranging_counter; STREAM_TO_UINT16(ranging_counter, value); log::info("ranging_counter:{}", ranging_counter); std::lock_guard<std::mutex> lock(data_mutex_); auto it = std::find_if(tracker->buffers_.begin(), tracker->buffers_.end(), [&ranging_counter](const DataBuffer& buffer) { return buffer.ranging_counter_ == ranging_counter; }); // If found, erase it if (it != tracker->buffers_.end()) { tracker->buffers_.erase(it); tracker->handling_control_point_command_ = false; } }; void SendResponseCode(ResponseCodeValue response_code_value, ClientTracker* tracker) { log::info("0x{:02x}, {}", (uint16_t)response_code_value, GetResponseOpcodeValueText(response_code_value)); std::vector<uint8_t> response(8, 0); response[0] = (uint8_t)EventCode::RESPONSE_CODE; response[1] = 0; // Null response[2] = (uint8_t)response_code_value; BTA_GATTS_HandleValueIndication( tracker->conn_id_, GetCharacteristic(kRasControlPointCharacteristic)->attribute_handle_, response, true); tracker->handling_control_point_command_ = false; } void OnServiceAdded(tGATT_STATUS status, int server_if, std::vector<btgatt_db_element_t> service) { log::info("status: {}, server_if: {}", gatt_status_text(status), server_if); Loading
system/bta/ras/ras_types.h +49 −0 Original line number Diff line number Diff line Loading @@ -63,4 +63,53 @@ static const uint32_t kFilterRangingData = 0x08; static const uint32_t kPctPhaseFormat = 0xA0; } // namespace feature enum class Opcode : uint8_t { GET_RANGING_DATA = 0x00, ACK_RANGING_DATA = 0x01, RETRIEVE_LOST_RANGING_DATA_SEGMENTS = 0x02, ABORT_OPERATION = 0x03, FILTER = 0x04, PCT_FORMAT = 0x05, }; static const uint8_t OPERATOR_NULL = 0x00; std::string GetOpcodeText(Opcode opcode); enum class EventCode : uint8_t { COMPLETE_RANGING_DATA_RESPONSE = 0x00, COMPLETE_LOST_RANGING_DATA_SEGMENT_RESPONSE = 0x01, RESPONSE_CODE = 0x02, }; enum class ResponseCodeValue : uint8_t { RESERVED_FOR_FUTURE_USE = 0x00, SUCCESS = 0x01, OP_CODE_NOT_SUPPORTED = 0x02, INVALID_OPERATOR = 0x03, OPERATOR_NOT_SUPPORTED = 0x04, INVALID_OPERAND = 0x05, ABORT_UNSUCCESSFUL = 0x06, PROCEDURE_NOT_COMPLETED = 0x07, OPERAND_NOT_SUPPORTED = 0x08, NO_RECORDS_FOUND = 0x09, }; std::string GetResponseOpcodeValueText(ResponseCodeValue response_code_value); struct ControlPointCommand { Opcode opcode_; uint8_t operator_; uint8_t operand_[6]; }; struct ControlPointResponse { EventCode event_code_; uint8_t operator_; uint8_t operand_[6]; }; bool ParseControlPointCommand(ControlPointCommand* command, const uint8_t* value, uint16_t len); } // namespace ras
system/bta/ras/ras_utils.cc +59 −0 Original line number Diff line number Diff line Loading @@ -55,4 +55,63 @@ std::string uuid::getUuidName(const bluetooth::Uuid& uuid) { } } bool ParseControlPointCommand(ControlPointCommand* command, const uint8_t* value, uint16_t len) { // Check for minimum expected length if (len != kControlPointCommandSize) { LOG_WARN("Invalid len %d", len); return false; } command->opcode_ = static_cast<Opcode>(value[0]); command->operator_ = value[1]; std::memcpy(command->operand_, value + 2, 6); return true; } std::string GetOpcodeText(Opcode opcode) { switch (opcode) { case Opcode::GET_RANGING_DATA: return "GET_RANGING_DATA"; case Opcode::ACK_RANGING_DATA: return "ACK_RANGING_DATA"; case Opcode::RETRIEVE_LOST_RANGING_DATA_SEGMENTS: return "RETRIEVE_LOST_RANGING_DATA_SEGMENTS"; case Opcode::ABORT_OPERATION: return "ABORT_OPERATION"; case Opcode::FILTER: return "FILTER"; case Opcode::PCT_FORMAT: return "PCT_FORMAT"; default: return "Unknown Opcode"; } } std::string GetResponseOpcodeValueText(ResponseCodeValue response_code_value) { switch (response_code_value) { case ResponseCodeValue::RESERVED_FOR_FUTURE_USE: return "RESERVED_FOR_FUTURE_USE"; case ResponseCodeValue::SUCCESS: return "SUCCESS"; case ResponseCodeValue::OP_CODE_NOT_SUPPORTED: return "OP_CODE_NOT_SUPPORTED"; case ResponseCodeValue::INVALID_OPERATOR: return "INVALID_OPERATOR"; case ResponseCodeValue::OPERATOR_NOT_SUPPORTED: return "OPERATOR_NOT_SUPPORTED"; case ResponseCodeValue::INVALID_OPERAND: return "INVALID_OPERAND"; case ResponseCodeValue::ABORT_UNSUCCESSFUL: return "ABORT_UNSUCCESSFUL"; case ResponseCodeValue::PROCEDURE_NOT_COMPLETED: return "PROCEDURE_NOT_COMPLETED"; case ResponseCodeValue::OPERAND_NOT_SUPPORTED: return "OPERAND_NOT_SUPPORTED"; case ResponseCodeValue::NO_RECORDS_FOUND: return "NO_RECORDS_FOUND"; default: return "Unknown Opcode"; } } } // namespace ras