1 // Copyright 2021 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 // The internal::Handler class is the base class for the transfer handler 26 // classes. Transfer handlers connect a transfer ID to the functions that do the 27 // actual reads and/or writes. 28 // 29 // Handlers use a stream::Reader or stream::Writer to do the reads and writes. 30 // They also provide optional Prepare and Finalize functions. 31 class Handler : public IntrusiveList<Handler>::Item { 32 public: 33 virtual ~Handler() = default; 34 id()35 constexpr uint32_t id() const { return transfer_id_; } 36 37 // Called at the beginning of a read transfer. The stream::Reader must be 38 // ready to read after a successful PrepareRead() call. Returning a non-OK 39 // status aborts the read. 40 // 41 // Status::Unimplemented() indicates that reads are not supported. 42 virtual Status PrepareRead() = 0; 43 44 // FinalizeRead() is called at the end of a read transfer. The status argument 45 // indicates whether the data transfer was successful or not. FinalizeRead(Status)46 virtual void FinalizeRead(Status) {} 47 48 // Called at the beginning of a write transfer. The stream::Writer must be 49 // ready to read after a successful PrepareRead() call. Returning a non-OK 50 // status aborts the write. 51 // 52 // Status::Unimplemented() indicates that writes are not supported. 53 virtual Status PrepareWrite() = 0; 54 55 // FinalizeWrite() is called at the end of a write transfer. The status 56 // argument indicates whether the data transfer was successful or not. 57 // 58 // Returning an error signals that the transfer failed, even if it had 59 // succeeded up to this point. FinalizeWrite(Status)60 virtual Status FinalizeWrite(Status) { return OkStatus(); } 61 62 protected: Handler(uint32_t transfer_id,stream::Reader * reader)63 constexpr Handler(uint32_t transfer_id, stream::Reader* reader) 64 : transfer_id_(transfer_id), reader_(reader) {} 65 Handler(uint32_t transfer_id,stream::Writer * writer)66 constexpr Handler(uint32_t transfer_id, stream::Writer* writer) 67 : transfer_id_(transfer_id), writer_(writer) {} 68 set_reader(stream::Reader & reader)69 void set_reader(stream::Reader& reader) { reader_ = &reader; } set_writer(stream::Writer & writer)70 void set_writer(stream::Writer& writer) { writer_ = &writer; } 71 72 private: 73 friend class Context; 74 75 // Prepares for either a read or write transfer. Prepare(internal::TransferType type)76 Status Prepare(internal::TransferType type) { 77 return type == internal::TransferType::kTransmit ? PrepareRead() 78 : PrepareWrite(); 79 } 80 81 // Only valid after a PrepareRead() or PrepareWrite() call that returns OK. stream()82 stream::Stream& stream() const { 83 PW_DASSERT(reader_ != nullptr); 84 return *reader_; 85 } 86 87 uint32_t transfer_id_; 88 89 // Use a union to support constexpr construction. 90 union { 91 stream::Reader* reader_; 92 stream::Writer* writer_; 93 }; 94 }; 95 96 } // namespace internal 97 98 class ReadOnlyHandler : public internal::Handler { 99 public: ReadOnlyHandler(uint32_t transfer_id)100 constexpr ReadOnlyHandler(uint32_t transfer_id) 101 : internal::Handler(transfer_id, static_cast<stream::Reader*>(nullptr)) {} 102 ReadOnlyHandler(uint32_t transfer_id,stream::Reader & reader)103 constexpr ReadOnlyHandler(uint32_t transfer_id, stream::Reader& reader) 104 : internal::Handler(transfer_id, &reader) {} 105 106 virtual ~ReadOnlyHandler() = default; 107 PrepareRead()108 Status PrepareRead() override { return OkStatus(); } 109 110 // Writes are not supported. PrepareWrite()111 Status PrepareWrite() final { return Status::PermissionDenied(); } 112 113 using internal::Handler::set_reader; 114 115 private: 116 using internal::Handler::set_writer; 117 }; 118 119 class WriteOnlyHandler : public internal::Handler { 120 public: WriteOnlyHandler(uint32_t transfer_id)121 constexpr WriteOnlyHandler(uint32_t transfer_id) 122 : internal::Handler(transfer_id, static_cast<stream::Writer*>(nullptr)) {} 123 WriteOnlyHandler(uint32_t transfer_id,stream::Writer & writer)124 constexpr WriteOnlyHandler(uint32_t transfer_id, stream::Writer& writer) 125 : internal::Handler(transfer_id, &writer) {} 126 127 virtual ~WriteOnlyHandler() = default; 128 129 // Reads are not supported. PrepareRead()130 Status PrepareRead() final { return Status::PermissionDenied(); } 131 PrepareWrite()132 Status PrepareWrite() override { return OkStatus(); } 133 134 using internal::Handler::set_writer; 135 136 private: 137 using internal::Handler::set_reader; 138 }; 139 140 class ReadWriteHandler : public internal::Handler { 141 public: ReadWriteHandler(uint32_t transfer_id)142 constexpr ReadWriteHandler(uint32_t transfer_id) 143 : internal::Handler(transfer_id, static_cast<stream::Reader*>(nullptr)) {} ReadWriteHandler(uint32_t transfer_id,stream::ReaderWriter & reader_writer)144 constexpr ReadWriteHandler(uint32_t transfer_id, 145 stream::ReaderWriter& reader_writer) 146 : internal::Handler(transfer_id, 147 &static_cast<stream::Reader&>(reader_writer)) {} 148 149 virtual ~ReadWriteHandler() = default; 150 151 // Both reads and writes are supported. PrepareRead()152 Status PrepareRead() override { return OkStatus(); } PrepareWrite()153 Status PrepareWrite() override { return OkStatus(); } 154 set_reader_writer(stream::ReaderWriter & reader_writer)155 void set_reader_writer(stream::ReaderWriter& reader_writer) { 156 set_reader(reader_writer); 157 } 158 }; 159 160 } // namespace pw::transfer 161