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 15 #include <array> 16 #include <cstddef> 17 #include <cstdint> 18 #include <cstdio> 19 20 #include "pw_assert/check.h" 21 #include "pw_hdlc/encoded_size.h" 22 #include "pw_hdlc/rpc_channel.h" 23 #include "pw_hdlc/rpc_packets.h" 24 #include "pw_log/log.h" 25 #include "pw_sync/mutex.h" 26 #include "pw_system/config.h" 27 #include "pw_system/io.h" 28 #include "pw_system/rpc_server.h" 29 30 namespace pw::system { 31 namespace { 32 33 constexpr size_t kMaxTransmissionUnit = PW_SYSTEM_MAX_TRANSMISSION_UNIT; 34 35 static_assert(kMaxTransmissionUnit == 36 hdlc::MaxEncodedFrameSize(rpc::cfg::kEncodingBufferSizeBytes)); 37 38 hdlc::FixedMtuChannelOutput<kMaxTransmissionUnit> hdlc_channel_output( 39 GetWriter(), PW_SYSTEM_DEFAULT_RPC_HDLC_ADDRESS, "HDLC channel"); 40 rpc::Channel channels[] = { 41 rpc::Channel::Create<kDefaultRpcChannelId>(&hdlc_channel_output)}; 42 rpc::Server server(channels); 43 44 constexpr size_t kDecoderBufferSize = 45 hdlc::Decoder::RequiredBufferSizeForFrameSize(kMaxTransmissionUnit); 46 // Declare a buffer for decoding incoming HDLC frames. 47 std::array<std::byte, kDecoderBufferSize> input_buffer; 48 hdlc::Decoder decoder(input_buffer); 49 50 std::array<std::byte, 1> data; 51 52 } // namespace 53 GetRpcServer()54rpc::Server& GetRpcServer() { return server; } 55 56 class RpcDispatchThread final : public thread::ThreadCore { 57 public: 58 RpcDispatchThread() = default; 59 RpcDispatchThread(const RpcDispatchThread&) = delete; 60 RpcDispatchThread(RpcDispatchThread&&) = delete; 61 RpcDispatchThread& operator=(const RpcDispatchThread&) = delete; 62 RpcDispatchThread& operator=(RpcDispatchThread&&) = delete; 63 Run()64 void Run() override { 65 PW_LOG_INFO("Running RPC server"); 66 while (true) { 67 auto ret_val = GetReader().Read(data); 68 if (ret_val.ok()) { 69 for (std::byte byte : ret_val.value()) { 70 if (auto result = decoder.Process(byte); result.ok()) { 71 hdlc::Frame& frame = result.value(); 72 if (frame.address() == PW_SYSTEM_DEFAULT_RPC_HDLC_ADDRESS) { 73 server.ProcessPacket(frame.data()); 74 } 75 } 76 } 77 } 78 } 79 } 80 }; 81 GetRpcDispatchThread()82thread::ThreadCore& GetRpcDispatchThread() { 83 static RpcDispatchThread rpc_dispatch_thread; 84 return rpc_dispatch_thread; 85 } 86 87 } // namespace pw::system 88