1 /* 2 * Copyright 2021 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 <sys/time.h> 21 #include <time.h> 22 23 #include <list> 24 #include <variant> 25 26 #include "common/time_util.h" 27 #include "has_ctp.h" 28 29 /* Journal and journal entry classes used by the state dumping functionality. */ 30 namespace bluetooth::le_audio { 31 namespace has { 32 static constexpr uint8_t kHasJournalNumRecords = 20; 33 34 struct HasJournalRecord { 35 /* Indicates which value the `event` contains (due to ambiguous uint8_t) */ 36 bool is_operation : 1, is_notification : 1, is_features_change : 1, 37 is_active_preset_change : 1; 38 std::variant<HasCtpOp, HasCtpNtf, uint8_t> event; 39 struct timespec timestamp; 40 41 /* Operation context handle to match on GATT write response */ 42 void* op_context_handle; 43 44 /* Status of the operation to be set once it gets completed */ 45 uint8_t op_status; 46 HasJournalRecordHasJournalRecord47 HasJournalRecord(const HasCtpOp& op, void* context) 48 : event(op), op_context_handle(context) { 49 clock_gettime(CLOCK_REALTIME, ×tamp); 50 is_operation = true; 51 is_notification = false; 52 is_features_change = false; 53 is_active_preset_change = false; 54 } 55 HasJournalRecordHasJournalRecord56 HasJournalRecord(const HasCtpNtf& ntf) : event(ntf) { 57 clock_gettime(CLOCK_REALTIME, ×tamp); 58 is_operation = false; 59 is_notification = true; 60 is_features_change = false; 61 is_active_preset_change = false; 62 } 63 HasJournalRecordHasJournalRecord64 HasJournalRecord(uint8_t value, bool is_feat_change) : event(value) { 65 clock_gettime(CLOCK_REALTIME, ×tamp); 66 is_operation = false; 67 is_notification = false; 68 if (is_feat_change) { 69 is_active_preset_change = false; 70 is_features_change = true; 71 } else { 72 is_active_preset_change = true; 73 is_features_change = false; 74 } 75 } 76 }; 77 std::ostream& operator<<(std::ostream& os, const HasJournalRecord& r); 78 79 template <class valT, size_t cache_max> 80 class CacheList { 81 public: Append(valT data)82 valT& Append(valT data) { 83 items_.push_front(std::move(data)); 84 85 if (items_.size() > cache_max) { 86 items_.pop_back(); 87 } 88 89 return items_.front(); 90 } 91 92 using iterator = typename std::list<valT>::iterator; begin(void)93 iterator begin(void) { return items_.begin(); } end(void)94 iterator end(void) { return items_.end(); } 95 96 using const_iterator = typename std::list<valT>::const_iterator; begin(void)97 const_iterator begin(void) const { return items_.begin(); } end(void)98 const_iterator end(void) const { return items_.end(); } 99 Erase(iterator it)100 void Erase(iterator it) { 101 if (it != items_.end()) items_.erase(it); 102 } 103 Clear(void)104 void Clear(void) { items_.clear(); } isEmpty(void)105 bool isEmpty(void) { return items_.empty(); } 106 107 private: 108 typename std::list<valT> items_; 109 }; 110 111 using HasJournal = CacheList<HasJournalRecord, kHasJournalNumRecords>; 112 } // namespace has 113 } // namespace bluetooth::le_audio 114