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