blob: 3beb102bf7277f88213fa1554b5fbfcdbcbf2212 [file] [log] [blame]
Alexei Frolov563946f2021-08-05 18:58:48 -07001// 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
15#include "pw_transfer/internal/context.h"
16
17#include "pw_assert/check.h"
18#include "pw_status/try.h"
19
20namespace pw::transfer::internal {
21
22Status Context::Start(Type type, Handler& handler) {
23 PW_DCHECK(!active());
24
25 if (type == kRead) {
26 PW_TRY(handler.PrepareRead());
27 } else {
28 PW_TRY(handler.PrepareWrite());
29 }
30
31 type_ = type;
32 handler_ = &handler;
33 offset_ = 0;
34 pending_bytes_ = 0;
35
36 return OkStatus();
37}
38
39void Context::Finish(Status status) {
40 PW_DCHECK(active());
41
42 if (type_ == kRead) {
43 handler_->FinalizeRead(status);
44 } else {
45 handler_->FinalizeWrite(status);
46 }
47
48 handler_ = nullptr;
49}
50
51Result<Context*> ContextPool::GetOrStartTransfer(uint32_t id) {
52 internal::Context* new_transfer = nullptr;
53
54 // Check if the ID belongs to an active transfer. If not, pick an inactive
55 // slot to start a new transfer.
56 for (Context& transfer : transfers_) {
57 if (transfer.active()) {
58 if (transfer.transfer_id() == id) {
59 return &transfer;
60 }
61 } else {
62 new_transfer = &transfer;
63 }
64 }
65
66 if (!new_transfer) {
67 return Status::ResourceExhausted();
68 }
69
70 // Try to start the new transfer by checking if a handler for it exists.
71 auto handler = std::find_if(handlers_.begin(), handlers_.end(), [&](auto& h) {
72 return h.id() == id;
73 });
74
75 if (handler == handlers_.end()) {
76 return Status::NotFound();
77 }
78
79 PW_TRY(new_transfer->Start(type_, *handler));
80 return new_transfer;
81}
82
83} // namespace pw::transfer::internal