1 // Copyright 2022 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include "pw_assert/assert.h" 17 #include "pw_containers/intrusive_list.h" 18 #include "pw_status/status.h" 19 #include "pw_stream/stream.h" 20 #include "pw_transfer/internal/event.h" 21 22 namespace pw::transfer { 23 namespace internal { 24 25 class Context; 26 27 } // namespace internal 28 29 // The Handler class is the base class for the transfer handler classes. 30 // Transfer handlers connect a transfer resource ID to a data stream, wrapped 31 // with initialization and cleanup procedures. 32 // 33 // Handlers use a stream::Reader or stream::Writer to do the reads and writes. 34 // They also provide optional Prepare and Finalize functions. 35 class Handler : public IntrusiveList<Handler>::Item { 36 public: 37 virtual ~Handler() = default; 38 id()39 constexpr uint32_t id() const { return resource_id_; } 40 41 // Called at the beginning of a read transfer. The stream::Reader must be 42 // ready to read after a successful PrepareRead() call. Returning a non-OK 43 // status aborts the read. 44 // 45 // Status::Unimplemented() indicates that reads are not supported. 46 virtual Status PrepareRead() = 0; 47 48 // FinalizeRead() is called at the end of a read transfer. The status argument 49 // indicates whether the data transfer was successful or not. FinalizeRead(Status)50 virtual void FinalizeRead(Status) {} 51 52 // Called at the beginning of a write transfer. The stream::Writer must be 53 // ready to read after a successful PrepareRead() call. Returning a non-OK 54 // status aborts the write. 55 // 56 // Status::Unimplemented() indicates that writes are not supported. 57 virtual Status PrepareWrite() = 0; 58 59 // FinalizeWrite() is called at the end of a write transfer. The status 60 // argument indicates whether the data transfer was successful or not. 61 // 62 // Returning an error signals that the transfer failed, even if it had 63 // succeeded up to this point. FinalizeWrite(Status)64 virtual Status FinalizeWrite(Status) { return OkStatus(); } 65 66 protected: Handler(uint32_t resource_id,stream::Reader * reader)67 constexpr Handler(uint32_t resource_id, stream::Reader* reader) 68 : resource_id_(resource_id), reader_(reader) {} 69 Handler(uint32_t resource_id,stream::Writer * writer)70 constexpr Handler(uint32_t resource_id, stream::Writer* writer) 71 : resource_id_(resource_id), writer_(writer) {} 72 set_reader(stream::Reader & reader)73 void set_reader(stream::Reader& reader) { reader_ = &reader; } set_writer(stream::Writer & writer)74 void set_writer(stream::Writer& writer) { writer_ = &writer; } 75 76 private: 77 friend class internal::Context; 78 79 // Prepares for either a read or write transfer. Prepare(internal::TransferType type)80 Status Prepare(internal::TransferType type) { 81 return type == internal::TransferType::kTransmit ? PrepareRead() 82 : PrepareWrite(); 83 } 84 85 // Only valid after a PrepareRead() or PrepareWrite() call that returns OK. stream()86 stream::Stream& stream() const { 87 PW_DASSERT(reader_ != nullptr); 88 return *reader_; 89 } 90 91 uint32_t resource_id_; 92 93 // Use a union to support constexpr construction. 94 union { 95 stream::Reader* reader_; 96 stream::Writer* writer_; 97 }; 98 }; 99 100 class ReadOnlyHandler : public Handler { 101 public: ReadOnlyHandler(uint32_t resource_id)102 constexpr ReadOnlyHandler(uint32_t resource_id) 103 : Handler(resource_id, static_cast<stream::Reader*>(nullptr)) {} 104 ReadOnlyHandler(uint32_t resource_id,stream::Reader & reader)105 constexpr ReadOnlyHandler(uint32_t resource_id, stream::Reader& reader) 106 : Handler(resource_id, &reader) {} 107 108 ~ReadOnlyHandler() override = default; 109 PrepareRead()110 Status PrepareRead() override { return OkStatus(); } 111 112 // Writes are not supported. PrepareWrite()113 Status PrepareWrite() final { return Status::PermissionDenied(); } 114 115 using Handler::set_reader; 116 117 private: 118 using Handler::set_writer; 119 }; 120 121 class WriteOnlyHandler : public Handler { 122 public: WriteOnlyHandler(uint32_t resource_id)123 constexpr WriteOnlyHandler(uint32_t resource_id) 124 : Handler(resource_id, static_cast<stream::Writer*>(nullptr)) {} 125 WriteOnlyHandler(uint32_t resource_id,stream::Writer & writer)126 constexpr WriteOnlyHandler(uint32_t resource_id, stream::Writer& writer) 127 : Handler(resource_id, &writer) {} 128 129 ~WriteOnlyHandler() override = default; 130 131 // Reads are not supported. PrepareRead()132 Status PrepareRead() final { return Status::PermissionDenied(); } 133 PrepareWrite()134 Status PrepareWrite() override { return OkStatus(); } 135 136 using Handler::set_writer; 137 138 private: 139 using Handler::set_reader; 140 }; 141 142 class ReadWriteHandler : public Handler { 143 public: ReadWriteHandler(uint32_t resource_id)144 constexpr ReadWriteHandler(uint32_t resource_id) 145 : Handler(resource_id, static_cast<stream::Reader*>(nullptr)) {} ReadWriteHandler(uint32_t resource_id,stream::ReaderWriter & reader_writer)146 constexpr ReadWriteHandler(uint32_t resource_id, 147 stream::ReaderWriter& reader_writer) 148 : Handler(resource_id, &static_cast<stream::Reader&>(reader_writer)) {} 149 150 ~ReadWriteHandler() override = default; 151 152 // Both reads and writes are supported. PrepareRead()153 Status PrepareRead() override { return OkStatus(); } PrepareWrite()154 Status PrepareWrite() override { return OkStatus(); } 155 set_reader_writer(stream::ReaderWriter & reader_writer)156 void set_reader_writer(stream::ReaderWriter& reader_writer) { 157 set_reader(reader_writer); 158 } 159 }; 160 161 } // namespace pw::transfer 162