• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 HIMSA II K/S - www.himsa.com.
3  * Represented by EHIMA - www.ehima.com
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #pragma once
19 
20 #include <queue>
21 #include <vector>
22 
23 #include "bta/include/bta_groups.h"
24 #include "osi/include/alarm.h"
25 #include "raw_address.h"
26 #include "types/bluetooth/uuid.h"
27 
28 namespace bluetooth {
29 namespace vc {
30 namespace internal {
31 
32 /* clang-format off */
33 /* Volume control point opcodes */
34 static constexpr uint8_t kControlPointOpcodeVolumeDown         = 0x00;
35 static constexpr uint8_t kControlPointOpcodeVolumeUp           = 0x01;
36 static constexpr uint8_t kControlPointOpcodeUnmuteVolumeDown   = 0x02;
37 static constexpr uint8_t kControlPointOpcodeUnmuteVolumeUp     = 0x03;
38 static constexpr uint8_t kControlPointOpcodeSetAbsoluteVolume  = 0x04;
39 static constexpr uint8_t kControlPointOpcodeUnmute             = 0x05;
40 static constexpr uint8_t kControlPointOpcodeMute               = 0x06;
41 
42 /* Volume offset control point opcodes */
43 static constexpr uint8_t kVolumeOffsetControlPointOpcodeSet                 = 0x01;
44 
45 /* Volume input control point opcodes */
46 static constexpr uint8_t kVolumeInputControlPointOpcodeSetGain              = 0x01;
47 static constexpr uint8_t kVolumeInputControlPointOpcodeUnmute               = 0x02;
48 static constexpr uint8_t kVolumeInputControlPointOpcodeMute                 = 0x03;
49 static constexpr uint8_t kVolumeInputControlPointOpcodeSetManualGainMode    = 0x04;
50 static constexpr uint8_t kVolumeInputControlPointOpcodeSetAutoGainMode      = 0x05;
51 
52 static const Uuid kVolumeControlUuid                  = Uuid::From16Bit(0x1844);
53 static const Uuid kVolumeControlStateUuid             = Uuid::From16Bit(0x2B7D);
54 static const Uuid kVolumeControlPointUuid             = Uuid::From16Bit(0x2B7E);
55 static const Uuid kVolumeFlagsUuid                    = Uuid::From16Bit(0x2B7F);
56 
57 static const Uuid kVolumeOffsetUuid                   = Uuid::From16Bit(0x1845);
58 static const Uuid kVolumeOffsetStateUuid              = Uuid::From16Bit(0x2B80);
59 static const Uuid kVolumeOffsetLocationUuid           = Uuid::From16Bit(0x2B81);
60 static const Uuid kVolumeOffsetControlPointUuid       = Uuid::From16Bit(0x2B82);
61 static const Uuid kVolumeOffsetOutputDescriptionUuid  = Uuid::From16Bit(0x2B83);
62 /* clang-format on */
63 
64 struct VolumeOperation {
65   int operation_id_;
66   int group_id_;
67 
68   bool started_;
69   bool is_autonomous_;
70 
71   uint8_t opcode_;
72   std::vector<uint8_t> arguments_;
73 
74   std::vector<RawAddress> devices_;
75   alarm_t* operation_timeout_;
76 
VolumeOperationVolumeOperation77   VolumeOperation(int operation_id, int group_id, bool is_autonomous, uint8_t opcode,
78                   std::vector<uint8_t> arguments,
79                   std::vector<RawAddress> devices)
80       : operation_id_(operation_id),
81         group_id_(group_id),
82         is_autonomous_(is_autonomous),
83         opcode_(opcode),
84         arguments_(arguments),
85         devices_(devices) {
86     auto name = "operation_timeout_" + std::to_string(operation_id);
87     operation_timeout_ = alarm_new(name.c_str());
88     started_ = false;
89   };
90 
~VolumeOperationVolumeOperation91   ~VolumeOperation() {
92     if (alarm_is_scheduled(operation_timeout_))
93       alarm_cancel(operation_timeout_);
94 
95     alarm_free(operation_timeout_);
96     operation_timeout_ = nullptr;
97   }
98 
IsGroupOperationVolumeOperation99   bool IsGroupOperation(void) {
100     return (group_id_ != bluetooth::groups::kGroupUnknown);
101   }
102 
IsStartedVolumeOperation103   bool IsStarted(void) { return started_; };
StartVolumeOperation104   void Start(void) { started_ = true; }
105 };
106 
107 struct VolumeOffset {
108   uint8_t id;
109   uint8_t change_counter;
110   int16_t offset;
111   uint32_t location;
112   uint16_t service_handle;
113   uint16_t state_handle;
114   uint16_t state_ccc_handle;
115   uint16_t audio_location_handle;
116   uint16_t audio_location_ccc_handle;
117   uint16_t audio_descr_handle;
118   uint16_t audio_descr_ccc_handle;
119   uint16_t control_point_handle;
120   bool audio_location_writable;
121   bool audio_descr_writable;
122 
VolumeOffsetVolumeOffset123   VolumeOffset(uint16_t service_handle)
124       : id(0),
125         change_counter(0),
126         offset(0),
127         location(0),
128         service_handle(service_handle),
129         state_handle(0),
130         state_ccc_handle(0),
131         audio_location_handle(0),
132         audio_location_ccc_handle(0),
133         audio_descr_handle(0),
134         audio_descr_ccc_handle(0),
135         control_point_handle(0),
136         audio_location_writable(false),
137         audio_descr_writable(false) {}
138 };
139 
140 class VolumeOffsets {
141  public:
Add(VolumeOffset & offset)142   void Add(VolumeOffset& offset) {
143     offset.id = (uint8_t)Size() + 1;
144     volume_offsets.push_back(offset);
145   }
146 
FindByLocation(uint8_t location)147   VolumeOffset* FindByLocation(uint8_t location) {
148     auto iter = std::find_if(volume_offsets.begin(), volume_offsets.end(),
149                              [&location](const VolumeOffset& item) {
150                                return item.location == location;
151                              });
152 
153     return (iter == volume_offsets.end()) ? nullptr : &(*iter);
154   }
155 
FindByServiceHandle(uint16_t service_handle)156   VolumeOffset* FindByServiceHandle(uint16_t service_handle) {
157     auto iter = std::find_if(volume_offsets.begin(), volume_offsets.end(),
158                              [&service_handle](const VolumeOffset& item) {
159                                return item.service_handle == service_handle;
160                              });
161 
162     return (iter == volume_offsets.end()) ? nullptr : &(*iter);
163   }
164 
FindById(uint16_t id)165   VolumeOffset* FindById(uint16_t id) {
166     auto iter =
167         std::find_if(volume_offsets.begin(), volume_offsets.end(),
168                      [&id](const VolumeOffset& item) { return item.id == id; });
169 
170     return (iter == volume_offsets.end()) ? nullptr : &(*iter);
171   }
172 
Clear()173   void Clear() { volume_offsets.clear(); }
174 
Size()175   size_t Size() { return volume_offsets.size(); }
176 
Dump(int fd)177   void Dump(int fd) {
178     std::stringstream stream;
179     int n = Size();
180     stream << "     == number of offsets: " << n << " == \n";
181 
182     for (int i = 0; i < n; i++) {
183       auto v = volume_offsets[i];
184       stream << "   id: " << +v.id << "\n"
185              << "    offset: " << +v.offset << "\n"
186              << "    changeCnt: " << +v.change_counter << "\n"
187              << "    location: " << +v.location << "\n"
188              << "    service_handle: " << +v.service_handle << "\n"
189              << "    audio_location_writable " << v.audio_location_writable
190              << "\n"
191              << "    audio_descr_writable: " << v.audio_descr_writable << "\n";
192     }
193     dprintf(fd, "%s", stream.str().c_str());
194   }
195 
196   std::vector<VolumeOffset> volume_offsets;
197 };
198 
199 }  // namespace internal
200 }  // namespace vc
201 }  // namespace bluetooth
202