xref: /aosp_15_r20/external/pigweed/pw_i2c/i2c_service.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2023 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker #include "pw_i2c/i2c_service.h"
15*61c4878aSAndroid Build Coastguard Worker 
16*61c4878aSAndroid Build Coastguard Worker #include <algorithm>
17*61c4878aSAndroid Build Coastguard Worker #include <chrono>
18*61c4878aSAndroid Build Coastguard Worker 
19*61c4878aSAndroid Build Coastguard Worker #include "pw_assert/check.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_chrono/system_clock.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_containers/vector.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_i2c/address.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/pwpb/server_reader_writer.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_status/status.h"
25*61c4878aSAndroid Build Coastguard Worker 
26*61c4878aSAndroid Build Coastguard Worker namespace pw::i2c {
27*61c4878aSAndroid Build Coastguard Worker namespace {
28*61c4878aSAndroid Build Coastguard Worker 
29*61c4878aSAndroid Build Coastguard Worker constexpr auto kI2cTimeout =
30*61c4878aSAndroid Build Coastguard Worker     chrono::SystemClock::for_at_least(std::chrono::milliseconds(100));
31*61c4878aSAndroid Build Coastguard Worker 
32*61c4878aSAndroid Build Coastguard Worker }  // namespace
33*61c4878aSAndroid Build Coastguard Worker 
I2cWrite(const pwpb::I2cWriteRequest::Message & request,rpc::PwpbUnaryResponder<pwpb::I2cWriteResponse::Message> & responder)34*61c4878aSAndroid Build Coastguard Worker void I2cService::I2cWrite(
35*61c4878aSAndroid Build Coastguard Worker     const pwpb::I2cWriteRequest::Message& request,
36*61c4878aSAndroid Build Coastguard Worker     rpc::PwpbUnaryResponder<pwpb::I2cWriteResponse::Message>& responder) {
37*61c4878aSAndroid Build Coastguard Worker   Initiator* initiator = initiator_selector_(request.bus_index);
38*61c4878aSAndroid Build Coastguard Worker   if (initiator == nullptr) {
39*61c4878aSAndroid Build Coastguard Worker     responder.Finish({}, Status::InvalidArgument()).IgnoreError();
40*61c4878aSAndroid Build Coastguard Worker     return;
41*61c4878aSAndroid Build Coastguard Worker   }
42*61c4878aSAndroid Build Coastguard Worker 
43*61c4878aSAndroid Build Coastguard Worker   constexpr auto kMaxWriteSize =
44*61c4878aSAndroid Build Coastguard Worker       pwpb::I2cWriteRequest::kRegisterAddressMaxSize +
45*61c4878aSAndroid Build Coastguard Worker       pwpb::I2cWriteRequest::kValueMaxSize;
46*61c4878aSAndroid Build Coastguard Worker   Vector<std::byte, kMaxWriteSize> write_buffer{};
47*61c4878aSAndroid Build Coastguard Worker   write_buffer.assign(std::begin(request.register_address),
48*61c4878aSAndroid Build Coastguard Worker                       std::end(request.register_address));
49*61c4878aSAndroid Build Coastguard Worker   std::copy(std::begin(request.value),
50*61c4878aSAndroid Build Coastguard Worker             std::end(request.value),
51*61c4878aSAndroid Build Coastguard Worker             std::back_inserter(write_buffer));
52*61c4878aSAndroid Build Coastguard Worker   auto result = initiator->WriteFor(
53*61c4878aSAndroid Build Coastguard Worker       Address{static_cast<uint16_t>(request.target_address)},
54*61c4878aSAndroid Build Coastguard Worker       write_buffer,
55*61c4878aSAndroid Build Coastguard Worker       kI2cTimeout);
56*61c4878aSAndroid Build Coastguard Worker   responder.Finish({}, result).IgnoreError();
57*61c4878aSAndroid Build Coastguard Worker }
58*61c4878aSAndroid Build Coastguard Worker 
I2cRead(const pwpb::I2cReadRequest::Message & request,rpc::PwpbUnaryResponder<pwpb::I2cReadResponse::Message> & responder)59*61c4878aSAndroid Build Coastguard Worker void I2cService::I2cRead(
60*61c4878aSAndroid Build Coastguard Worker     const pwpb::I2cReadRequest::Message& request,
61*61c4878aSAndroid Build Coastguard Worker     rpc::PwpbUnaryResponder<pwpb::I2cReadResponse::Message>& responder) {
62*61c4878aSAndroid Build Coastguard Worker   constexpr auto kMaxReadSize = pwpb::I2cReadResponse::kValueMaxSize;
63*61c4878aSAndroid Build Coastguard Worker 
64*61c4878aSAndroid Build Coastguard Worker   Initiator* initiator = initiator_selector_(request.bus_index);
65*61c4878aSAndroid Build Coastguard Worker   if (initiator == nullptr || request.read_size > kMaxReadSize) {
66*61c4878aSAndroid Build Coastguard Worker     responder.Finish({}, Status::InvalidArgument()).IgnoreError();
67*61c4878aSAndroid Build Coastguard Worker     return;
68*61c4878aSAndroid Build Coastguard Worker   }
69*61c4878aSAndroid Build Coastguard Worker   Vector<std::byte, kMaxReadSize> value{};
70*61c4878aSAndroid Build Coastguard Worker   value.resize(request.read_size);
71*61c4878aSAndroid Build Coastguard Worker   auto result = initiator->WriteReadFor(
72*61c4878aSAndroid Build Coastguard Worker       Address{static_cast<uint16_t>(request.target_address)},
73*61c4878aSAndroid Build Coastguard Worker       request.register_address,
74*61c4878aSAndroid Build Coastguard Worker       {value.data(), value.size()},
75*61c4878aSAndroid Build Coastguard Worker       kI2cTimeout);
76*61c4878aSAndroid Build Coastguard Worker 
77*61c4878aSAndroid Build Coastguard Worker   if (result.ok()) {
78*61c4878aSAndroid Build Coastguard Worker     responder.Finish({value}, OkStatus()).IgnoreError();
79*61c4878aSAndroid Build Coastguard Worker   } else {
80*61c4878aSAndroid Build Coastguard Worker     responder.Finish({}, result).IgnoreError();
81*61c4878aSAndroid Build Coastguard Worker   }
82*61c4878aSAndroid Build Coastguard Worker }
83*61c4878aSAndroid Build Coastguard Worker 
84*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::i2c
85