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, is_active_preset_change : 1; 37 std::variant<HasCtpOp, HasCtpNtf, uint8_t> event; 38 struct timespec timestamp; 39 40 /* Operation context handle to match on GATT write response */ 41 void* op_context_handle; 42 43 /* Status of the operation to be set once it gets completed */ 44 uint8_t op_status; 45 HasJournalRecordHasJournalRecord46 HasJournalRecord(const HasCtpOp& op, void* context) : event(op), op_context_handle(context) { 47 clock_gettime(CLOCK_REALTIME, ×tamp); 48 is_operation = true; 49 is_notification = false; 50 is_features_change = false; 51 is_active_preset_change = false; 52 } 53 HasJournalRecordHasJournalRecord54 HasJournalRecord(const HasCtpNtf& ntf) : event(ntf) { 55 clock_gettime(CLOCK_REALTIME, ×tamp); 56 is_operation = false; 57 is_notification = true; 58 is_features_change = false; 59 is_active_preset_change = false; 60 } 61 HasJournalRecordHasJournalRecord62 HasJournalRecord(uint8_t value, bool is_feat_change) : event(value) { 63 clock_gettime(CLOCK_REALTIME, ×tamp); 64 is_operation = false; 65 is_notification = false; 66 if (is_feat_change) { 67 is_active_preset_change = false; 68 is_features_change = true; 69 } else { 70 is_active_preset_change = true; 71 is_features_change = false; 72 } 73 } 74 }; 75 std::ostream& operator<<(std::ostream& os, const HasJournalRecord& r); 76 77 template <class valT, size_t cache_max> 78 class CacheList { 79 public: Append(valT data)80 valT& Append(valT data) { 81 items_.push_front(std::move(data)); 82 83 if (items_.size() > cache_max) { 84 items_.pop_back(); 85 } 86 87 return items_.front(); 88 } 89 90 using iterator = typename std::list<valT>::iterator; begin(void)91 iterator begin(void) { return items_.begin(); } end(void)92 iterator end(void) { return items_.end(); } 93 94 using const_iterator = typename std::list<valT>::const_iterator; begin(void)95 const_iterator begin(void) const { return items_.begin(); } end(void)96 const_iterator end(void) const { return items_.end(); } 97 Erase(iterator it)98 void Erase(iterator it) { 99 if (it != items_.end()) { 100 items_.erase(it); 101 } 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