• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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