1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * @file 19 * This file includes definitions for the Socket interface interface to radio 20 * (RCP). 21 */ 22 23 #include "lib/spinel/spinel_interface.hpp" 24 #include "lib/url/url.hpp" 25 #include "logger.hpp" 26 27 namespace aidl { 28 namespace android { 29 namespace hardware { 30 namespace threadnetwork { 31 32 /** 33 * Defines a Socket interface to the Radio Co-processor (RCP) 34 * 35 */ 36 class SocketInterface : public ot::Spinel::SpinelInterface, 37 public ot::Posix::Logger<SocketInterface> { 38 public: 39 static const char kLogModuleName[]; ///< Module name used for logging. 40 41 /** 42 * Initializes the object. 43 * 44 * @param[in] aRadioUrl RadioUrl parsed from radio url. 45 * 46 */ 47 explicit SocketInterface(const ot::Url::Url& aRadioUrl); 48 49 /** 50 * This destructor deinitializes the object. 51 * 52 */ 53 ~SocketInterface(); 54 55 /** 56 * Initializes the interface to the Radio Co-processor (RCP) 57 * 58 * @note This method should be called before reading and sending Spinel 59 * frames to the interface. 60 * 61 * @param[in] aCallback Callback on frame received 62 * @param[in] aCallbackContext Callback context 63 * @param[in] aFrameBuffer A reference to a `RxFrameBuffer` object. 64 * 65 * @retval OT_ERROR_NONE The interface is initialized successfully 66 * @retval OT_ERROR_ALREADY The interface is already initialized. 67 * @retval OT_ERROR_FAILED Failed to initialize the interface. 68 * 69 */ 70 otError Init(ReceiveFrameCallback aCallback, void* aCallbackContext, 71 RxFrameBuffer& aFrameBuffer); 72 73 /** 74 * Deinitializes the interface to the RCP. 75 * 76 */ 77 void Deinit(void); 78 79 /** 80 * Sends a Spinel frame to Radio Co-processor (RCP) over the 81 * socket. 82 * 83 * @param[in] aFrame A pointer to buffer containing the Spinel frame to 84 * send. 85 * @param[in] aLength The length (number of bytes) in the frame. 86 * 87 * @retval OT_ERROR_NONE Successfully sent the Spinel frame. 88 * @retval OT_ERROR_FAILED Failed to send a frame. 89 * 90 */ 91 otError SendFrame(const uint8_t* aFrame, uint16_t aLength); 92 93 /** 94 * Waits for receiving part or all of Spinel frame within specified 95 * interval. 96 * 97 * @param[in] aTimeout The timeout value in microseconds. 98 * 99 * @retval OT_ERROR_NONE Part or all of Spinel frame is 100 * received. 101 * @retval OT_ERROR_RESPONSE_TIMEOUT No Spinel frame is received within @p 102 * aTimeout. 103 * @retval OT_EXIT_FAILURE RCP error 104 * 105 */ 106 otError WaitForFrame(uint64_t aTimeoutUs); 107 108 /** 109 * Updates the file descriptor sets with file descriptors used by the radio 110 * driver. 111 * 112 * @param[in,out] aMainloopContext A pointer to the mainloop context 113 * containing fd_sets. 114 * 115 */ 116 void UpdateFdSet(void* aMainloopContext); 117 118 /** 119 * Performs radio driver processing. 120 * 121 * @param[in] aMainloopContext A pointer to the mainloop context 122 * containing fd_sets. 123 * 124 */ 125 void Process(const void* aMainloopContext); 126 127 /** 128 * Returns the bus speed between the host and the radio. 129 * 130 * @return Bus speed in bits/second. 131 * 132 */ GetBusSpeed(void) const133 uint32_t GetBusSpeed(void) const { return 1000000; } 134 135 /** 136 * Hardware resets the RCP. 137 * 138 * @retval OT_ERROR_NONE Successfully reset the RCP. 139 * @retval OT_ERROR_NOT_IMPLEMENT The hardware reset is not implemented. 140 * 141 */ HardwareReset(void)142 otError HardwareReset(void) { return OT_ERROR_NOT_IMPLEMENTED; } 143 144 /** 145 * Returns the RCP interface metrics. 146 * 147 * @return The RCP interface metrics. 148 * 149 */ GetRcpInterfaceMetrics(void) const150 const otRcpInterfaceMetrics* GetRcpInterfaceMetrics(void) const { return &mInterfaceMetrics; } 151 152 /** 153 * Indicates whether or not the given interface matches this interface name. 154 * 155 * @param[in] aInterfaceName A pointer to the interface name. 156 * 157 * @retval TRUE The given interface name matches this interface name. 158 * @retval FALSE The given interface name doesn't match this interface 159 * name. 160 */ IsInterfaceNameMatch(const char * aInterfaceName)161 static bool IsInterfaceNameMatch(const char* aInterfaceName) { 162 static const char kInterfaceName[] = "spinel+socket"; 163 return (strncmp(aInterfaceName, kInterfaceName, strlen(kInterfaceName)) == 0); 164 } 165 166 private: 167 /** 168 * Instructs `SocketInterface` to read data from radio over the 169 * socket. 170 * 171 * If a full Spinel frame is received, this method invokes the 172 * `HandleSocketFrame()` (on the `aCallback` object from constructor) to 173 * pass the received frame to be processed. 174 * 175 */ 176 void Read(void); 177 178 /** 179 * Writes a given frame to the socket. 180 * 181 * @param[in] aFrame A pointer to buffer containing the frame to write. 182 * @param[in] aLength The length (number of bytes) in the frame. 183 * 184 */ 185 void Write(const uint8_t* aFrame, uint16_t aLength); 186 187 /** 188 * Process received data. 189 * 190 * If a full frame is finished processing and we obtain the raw Spinel 191 * frame, this method invokes the `HandleSocketFrame()` (on the `aCallback` 192 * object from constructor) to pass the received frame to be processed. 193 * 194 * @param[in] aBuffer A pointer to buffer containing data. 195 * @param[in] aLength The length (number of bytes) in the buffer. 196 * 197 */ 198 void ProcessReceivedData(const uint8_t* aBuffer, uint16_t aLength); 199 200 static void HandleSocketFrame(void* aContext, otError aError); 201 void HandleSocketFrame(otError aError); 202 203 /** 204 * Opens file specified by aRadioUrl. 205 * 206 * @param[in] aRadioUrl A reference to object containing path to file and 207 * data for configuring the connection with tty type file. 208 * 209 * @retval The file descriptor of newly opened file. 210 * @retval -1 Fail to open file. 211 * 212 */ 213 int OpenFile(const ot::Url::Url& aRadioUrl); 214 215 /** 216 * Closes file associated with the file descriptor. 217 * 218 */ 219 void CloseFile(void); 220 221 /** 222 * Check if socket file is created. 223 * 224 * @param[in] aPath Socket file path name. 225 * 226 * @retval TRUE The required socket file is created. 227 * @retval FALSE The required socket file is not created. 228 * 229 */ 230 bool IsSocketFileExisted(const char* aPath); 231 232 /** 233 * Wait until the socket file is created. 234 * 235 * @param[in] aPath Socket file path name. 236 * 237 */ 238 void WaitForSocketFileCreated(const char* aPath); 239 240 enum { 241 kMaxSelectTimeMs = 2000, ///< Maximum wait time in Milliseconds for file 242 ///< descriptor to become available. 243 }; 244 245 ReceiveFrameCallback mReceiveFrameCallback; 246 void* mReceiveFrameContext; 247 RxFrameBuffer* mReceiveFrameBuffer; 248 249 int mSockFd; 250 const ot::Url::Url& mRadioUrl; 251 252 otRcpInterfaceMetrics mInterfaceMetrics; 253 254 // Non-copyable, intentionally not implemented. 255 SocketInterface(const SocketInterface&); 256 SocketInterface& operator=(const SocketInterface&); 257 }; 258 259 } // namespace threadnetwork 260 } // namespace hardware 261 } // namespace android 262 } // namespace aidl 263