1 // Copyright 2023 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 #define PW_LOG_MODULE_NAME "IO"
16
17 #include "pw_digital_io/digital_io_service.h"
18
19 #include "pw_digital_io/digital_io.pwpb.h"
20 #include "pw_log/log.h"
21 #include "pw_result/result.h"
22 #include "pw_rpc/pwpb/server_reader_writer.h"
23 #include "pw_status/status.h"
24
25 namespace pw::digital_io {
26
Enable(const pwpb::DigitalIoEnableRequest::Message & request,rpc::PwpbUnaryResponder<pwpb::DigitalIoEnableResponse::Message> & responder)27 void DigitalIoService::Enable(
28 const pwpb::DigitalIoEnableRequest::Message& request,
29 rpc::PwpbUnaryResponder<pwpb::DigitalIoEnableResponse::Message>&
30 responder) {
31 Status result = OkStatus();
32 if (request.line_index >= lines_.size()) {
33 result = Status::InvalidArgument();
34 } else {
35 auto& line = lines_[request.line_index].get();
36 if (request.enable) {
37 result = line.Enable();
38 } else {
39 result = line.Disable();
40 }
41 }
42
43 if (const auto finished = responder.Finish({}, result); !finished.ok()) {
44 PW_LOG_ERROR("Enable failed to send response %d", finished.code());
45 }
46 }
47
SetState(const pwpb::DigitalIoSetStateRequest::Message & request,rpc::PwpbUnaryResponder<pwpb::DigitalIoSetStateResponse::Message> & responder)48 void DigitalIoService::SetState(
49 const pwpb::DigitalIoSetStateRequest::Message& request,
50 rpc::PwpbUnaryResponder<pwpb::DigitalIoSetStateResponse::Message>&
51 responder) {
52 Status result = OkStatus();
53 if (request.line_index >= lines_.size()) {
54 result = Status::InvalidArgument();
55 } else {
56 auto& line = lines_[request.line_index].get();
57 if (!line.provides_output()) {
58 result = Status::InvalidArgument();
59 } else {
60 if (request.state == pwpb::DigitalIoState::kActive) {
61 result = line.SetStateActive();
62 } else {
63 result = line.SetStateInactive();
64 }
65 }
66 }
67
68 if (const auto finished = responder.Finish({}, result); !finished.ok()) {
69 PW_LOG_ERROR("SetState failed to send response %d", finished.code());
70 }
71 }
72
GetState(const pwpb::DigitalIoGetStateRequest::Message & request,rpc::PwpbUnaryResponder<pwpb::DigitalIoGetStateResponse::Message> & responder)73 void DigitalIoService::GetState(
74 const pwpb::DigitalIoGetStateRequest::Message& request,
75 rpc::PwpbUnaryResponder<pwpb::DigitalIoGetStateResponse::Message>&
76 responder) {
77 pw::Result<State> result;
78 if (request.line_index >= lines_.size()) {
79 result = pw::Status::InvalidArgument();
80 } else {
81 auto& line = lines_[request.line_index].get();
82 if (!line.provides_input()) {
83 result = pw::Status::InvalidArgument();
84 } else {
85 result = line.GetState();
86 }
87 }
88
89 auto finished = pw::OkStatus();
90 if (result.ok()) {
91 pwpb::DigitalIoState state = *result == State::kActive
92 ? pwpb::DigitalIoState::kActive
93 : pwpb::DigitalIoState::kInactive;
94 finished = responder.Finish({.state = state}, OkStatus());
95 } else {
96 finished = responder.Finish({}, result.status());
97 }
98
99 if (!finished.ok()) {
100 PW_LOG_ERROR("GetState failed to send response %d", finished.code());
101 }
102 }
103
104 } // namespace pw::digital_io
105