1 /*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "model/controller/isochronous_connection_handler.h"
18
19 #include "hci/address.h"
20 #include "log.h"
21
22 namespace rootcanal {
23
24 using bluetooth::hci::ErrorCode;
25
26 std::unique_ptr<bluetooth::hci::LeSetCigParametersCompleteBuilder>
SetCigParameters(GroupParameters group_parameters,std::vector<StreamParameters> & streams,std::vector<uint16_t> handles)27 IsochronousConnectionHandler::SetCigParameters(
28 GroupParameters group_parameters, std::vector<StreamParameters>& streams,
29 std::vector<uint16_t> handles) {
30 if (groups_.count(group_parameters.id) != 0) {
31 if (groups_.at(group_parameters.id).HasStreams()) {
32 return bluetooth::hci::LeSetCigParametersCompleteBuilder::Create(
33 1, ErrorCode::COMMAND_DISALLOWED, group_parameters.id, {});
34 }
35 groups_.erase(group_parameters.id);
36 }
37
38 // TODO: Limit groups and return ErrorCode::MEMORY_CAPACITY_EXCEEDED
39 // TODO: Limit connections return ErrorCode::CONNECTION_LIMIT_EXCEEDED
40
41 std::vector<ConnectedIsochronousStream> created_streams;
42 for (size_t i = 0; i < streams.size(); i++) {
43 streams[i].handle = handles[i];
44 streams[i].group_id = group_parameters.id;
45 created_streams.emplace_back(streams[i]);
46 cis_to_group_.emplace(handles[i], group_parameters.id);
47 }
48
49 groups_.emplace(std::piecewise_construct,
50 std::forward_as_tuple(group_parameters.id),
51 std::forward_as_tuple(group_parameters, created_streams));
52
53 return bluetooth::hci::LeSetCigParametersCompleteBuilder::Create(
54 1, ErrorCode::SUCCESS, group_parameters.id, handles);
55 }
56
RemoveCig(uint8_t cig_id)57 bluetooth::hci::ErrorCode IsochronousConnectionHandler::RemoveCig(
58 uint8_t cig_id) {
59 if (groups_.count(cig_id) != 0) {
60 return ErrorCode::UNKNOWN_CONNECTION;
61 }
62 if (groups_.at(cig_id).HasConnectedStream()) {
63 return ErrorCode::COMMAND_DISALLOWED;
64 }
65 groups_.erase(cig_id);
66 auto copy = cis_to_group_;
67 cis_to_group_.clear();
68 for (auto pair : cis_to_group_) {
69 if (pair.second != cig_id) {
70 cis_to_group_.emplace(pair.first, pair.second);
71 }
72 }
73 return ErrorCode::SUCCESS;
74 }
75
HasHandle(uint16_t handle) const76 bool IsochronousConnectionHandler::HasHandle(uint16_t handle) const {
77 return cis_to_group_.count(handle) != 0;
78 }
79
GetGroupId(uint16_t handle) const80 uint8_t IsochronousConnectionHandler::GetGroupId(uint16_t handle) const {
81 return cis_to_group_.at(handle);
82 }
83
GetStreamParameters(uint16_t handle) const84 StreamParameters IsochronousConnectionHandler::GetStreamParameters(
85 uint16_t handle) const {
86 return groups_.at(cis_to_group_.at(handle)).GetStreamParameters(handle);
87 }
88
GetGroupParameters(uint8_t id) const89 GroupParameters IsochronousConnectionHandler::GetGroupParameters(
90 uint8_t id) const {
91 return groups_.at(id).GetParameters();
92 }
93
GetStreamIsConnected(uint16_t handle) const94 bool IsochronousConnectionHandler::GetStreamIsConnected(uint16_t handle) const {
95 return groups_.at(cis_to_group_.at(handle)).StreamIsConnected(handle);
96 }
97
98 } // namespace rootcanal
99