1 /* 2 * Copyright (C) 2020 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 #ifndef CHPP_CLIENTS_H_ 18 #define CHPP_CLIENTS_H_ 19 20 #include <stdbool.h> 21 #include <stddef.h> 22 #include <stdint.h> 23 24 #include "chpp/app.h" 25 #include "chpp/condition_variable.h" 26 #include "chpp/macros.h" 27 #include "chpp/mutex.h" 28 #include "chre_api/chre/common.h" 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 /************************************************ 35 * Public Definitions 36 ***********************************************/ 37 38 /** 39 * Uses chppAllocClientRequest() to allocate a client request message of a 40 * specific type and its corresponding length. 41 * 42 * @param clientState State variable of the client. 43 * @param type Type of response. 44 * 45 * @return Pointer to allocated memory 46 */ 47 #define chppAllocClientRequestFixed(clientState, type) \ 48 (type *)chppAllocClientRequest(clientState, sizeof(type)) 49 50 /** 51 * Uses chppAllocClientRequest() to allocate a variable-length client request 52 * message of a specific type. 53 * 54 * @param clientState State variable of the client. 55 * @param type Type of response which includes an arrayed member. 56 * @param count number of items in the array of arrayField. 57 * @param arrayField The arrayed member field. 58 * 59 * @return Pointer to allocated memory 60 */ 61 #define chppAllocClientRequestTypedArray(clientState, type, count, arrayField) \ 62 (type *)chppAllocClientRequest( \ 63 clientState, sizeof(type) + (count)*sizeof_member(type, arrayField[0])) 64 65 /** 66 * Maintains the basic state of a client. 67 * This is expected to be included once in the (context) status variable of 68 * each client. 69 */ 70 struct ChppClientState { 71 struct ChppAppState *appContext; // Pointer to app layer context 72 struct ChppRequestResponseState 73 *rRStates; // Pointer to array of request-response states, if any 74 uint8_t index; // Index of this client 75 uint8_t handle; // Handle number for this client 76 uint8_t transaction; // Next Transaction ID to be used 77 78 uint8_t openState; // As defined in enum ChppOpenState 79 bool pseudoOpen : 1; // Client to be opened upon a reset 80 bool initialized : 1; // Is initialized 81 bool everInitialized : 1; // Synchronization primitives initialized 82 83 bool responseReady : 1; // For sync. request/responses 84 struct ChppMutex responseMutex; 85 struct ChppConditionVariable responseCondVar; 86 }; 87 88 #ifdef CHPP_CLIENT_ENABLED_CHRE_WWAN 89 #define CHPP_CLIENT_ENABLED_WWAN 90 #endif 91 92 #ifdef CHPP_CLIENT_ENABLED_CHRE_WIFI 93 #define CHPP_CLIENT_ENABLED_WIFI 94 #endif 95 96 #ifdef CHPP_CLIENT_ENABLED_CHRE_GNSS 97 #define CHPP_CLIENT_ENABLED_GNSS 98 #endif 99 100 #if defined(CHPP_CLIENT_ENABLED_LOOPBACK) || \ 101 defined(CHPP_CLIENT_ENABLED_TIMESYNC) || \ 102 defined(CHPP_CLIENT_ENABLED_DISCOVERY) || \ 103 defined(CHPP_CLIENT_ENABLED_WWAN) || defined(CHPP_CLIENT_ENABLED_WIFI) || \ 104 defined(CHPP_CLIENT_ENABLED_GNSS) 105 #define CHPP_CLIENT_ENABLED 106 #endif 107 108 #define CHPP_CLIENT_REQUEST_TIMEOUT_INFINITE CHPP_TIME_MAX 109 110 #ifndef CHPP_CLIENT_REQUEST_TIMEOUT_DEFAULT 111 #define CHPP_CLIENT_REQUEST_TIMEOUT_DEFAULT CHRE_ASYNC_RESULT_TIMEOUT_NS 112 #endif 113 114 // Default timeout for discovery completion. 115 #ifndef CHPP_DISCOVERY_DEFAULT_TIMEOUT_MS 116 #define CHPP_DISCOVERY_DEFAULT_TIMEOUT_MS UINT64_C(10000) // 10s 117 #endif 118 119 /************************************************ 120 * Public functions 121 ***********************************************/ 122 123 /** 124 * Registers common clients with the CHPP app layer. These clients are enabled 125 * by CHPP_CLIENT_ENABLED_xxxx definitions. This function is automatically 126 * called by chppAppInit(). 127 * 128 * @param context Maintains status for each app layer instance. 129 */ 130 void chppRegisterCommonClients(struct ChppAppState *context); 131 132 /** 133 * Deregisters common clients with the CHPP app layer. These clients are enabled 134 * by CHPP_CLIENT_ENABLED_xxxx definitions. This function is automatically 135 * called by chppAppDeinit(). 136 * 137 * @param context Maintains status for each app layer instance. 138 */ 139 void chppDeregisterCommonClients(struct ChppAppState *context); 140 141 /** 142 * Registers a new client on CHPP. This function is to be called by the 143 * platform initialization code for every non-common client available on a 144 * server (if any), i.e. except those that are registered through 145 * chppRegisterCommonClients(). 146 * 147 * Registered clients are matched with discovered services during discovery. 148 * When a match succeeds, the client's initialization function (pointer) is 149 * called, assigning them their handle number. 150 * 151 * Note that the maximum number of clients that can be registered on a platform 152 * can specified as CHPP_MAX_REGISTERED_CLIENTS by the initialization code. 153 * Otherwise, a default value will be used. 154 * 155 * @param appContext Maintains status for each app layer instance. 156 * @param clientContext Maintains status for each client instance. 157 * @param clientState State variable of the client. 158 * @param rRStates Pointer to array of request-response states, if any. 159 * @param newClient The client to be registered on this platform. 160 */ 161 void chppRegisterClient(struct ChppAppState *appContext, void *clientContext, 162 struct ChppClientState *clientState, 163 struct ChppRequestResponseState *rRStates, 164 const struct ChppClient *newClient); 165 166 /** 167 * Initializes basic CHPP clients. 168 * 169 * @param context Maintains status for each app layer instance. 170 */ 171 void chppInitBasicClients(struct ChppAppState *context); 172 173 /** 174 * Initializes a client. This function must be called when a client is matched 175 * with a service during discovery to provides its handle number. 176 * 177 * @param clientState State variable of the client. 178 * @param handle Handle number for this client. 179 */ 180 void chppClientInit(struct ChppClientState *clientState, uint8_t handle); 181 182 /** 183 * Deinitializes a client. 184 * 185 * @param clientState State variable of the client. 186 */ 187 void chppClientDeinit(struct ChppClientState *clientState); 188 189 /** 190 * Deinitializes basic clients. 191 * 192 * @param context Maintains status for each app layer instance. 193 */ 194 void chppDeinitBasicClients(struct ChppAppState *context); 195 196 /** 197 * Deinitializes all matched clients. 198 * 199 * @param context Maintains status for each app layer instance. 200 */ 201 void chppDeinitMatchedClients(struct ChppAppState *context); 202 203 /** 204 * Allocates a client request message of a specified length, populating the 205 * (app layer) client request header, including the sequence ID. The 206 * next-sequence ID stored in the client state variable is subsequently 207 * incremented. 208 * 209 * It is expected that for most use cases, the chppAllocClientRequestFixed() 210 * or chppAllocClientRequestTypedArray() macros shall be used rather than 211 * calling this function directly. 212 * 213 * @param clientState State variable of the client. 214 * @param len Length of the response message (including header) in bytes. Note 215 * that the specified length must be at least equal to the lendth of the app 216 * layer header. 217 * 218 * @return Pointer to allocated memory 219 */ 220 struct ChppAppHeader *chppAllocClientRequest( 221 struct ChppClientState *clientState, size_t len); 222 223 /** 224 * Uses chppAllocClientRequest() to allocate a specific client request command 225 * without any additional payload. 226 * 227 * @param clientState State variable of the client. 228 * @param command Type of response. 229 * 230 * @return Pointer to allocated memory 231 */ 232 struct ChppAppHeader *chppAllocClientRequestCommand( 233 struct ChppClientState *clientState, uint16_t command); 234 235 /** 236 * This function shall be called for all outgoing client requests in order to 237 * A) Timestamp them, and 238 * B) Save their Transaction ID 239 * as part of the request/response's ChppRequestResponseState struct. 240 * 241 * This function prints an error message if a duplicate request is sent 242 * while outstanding request is still pending without a response. 243 * 244 * @param clientState State of the client sending the client request. 245 * @param transactionId The transaction ID to use when loading the app. 246 * @param rRState Maintains the basic state for each request/response 247 * functionality of a client. 248 * @param requestHeader Client request header. 249 */ 250 void chppClientTimestampRequest(struct ChppClientState *clientState, 251 struct ChppRequestResponseState *rRState, 252 struct ChppAppHeader *requestHeader, 253 uint64_t timeoutNs); 254 255 /** 256 * This function shall be called for incoming responses to a client request in 257 * order to 258 * A) Verify the correct transaction ID 259 * B) Timestamp them, and 260 * C) Mark them as fulfilled 261 * D) TODO: check for timeout 262 * 263 * This function prints an error message if a response is received without an 264 * outstanding request. 265 * 266 * @param clientState State of the client sending the client request. 267 * @param rRState Maintains the basic state for each request/response 268 * functionality of a client. 269 * @param requestHeader Client request header. 270 * 271 * @return false if there is an error. True otherwise. 272 */ 273 bool chppClientTimestampResponse(struct ChppClientState *clientState, 274 struct ChppRequestResponseState *rRState, 275 const struct ChppAppHeader *responseHeader); 276 277 /** 278 * Timestamps a client request using chppClientTimestampResponse() and enqueues 279 * it using chppEnqueueTxDatagramOrFail(). 280 * 281 * Refer to their respective documentation for details. 282 * 283 * Note that the ownership of buf is taken from the caller when this method is 284 * invoked. 285 * 286 * @param clientState State of the client sending the client request. 287 * @param rRState Maintains the basic state for each request/response 288 * functionality of a client. 289 * @param buf Datagram payload allocated through chppMalloc. Cannot be null. 290 * @param len Datagram length in bytes. 291 * @param timeoutNs Time in nanoseconds before a timeout response is generated. 292 * Zero means no timeout response. 293 * 294 * @return True informs the sender that the datagram was successfully enqueued. 295 * False informs the sender that the queue was full and the payload discarded. 296 */ 297 bool chppSendTimestampedRequestOrFail(struct ChppClientState *clientState, 298 struct ChppRequestResponseState *rRState, 299 void *buf, size_t len, 300 uint64_t timeoutNs); 301 302 /** 303 * Similar to chppSendTimestampedRequestOrFail() but blocks execution until a 304 * response is received. Used for synchronous requests. 305 * 306 * In order to use this function, clientState->responseNotifier must have been 307 * initialized using chppNotifierInit() upon initialization of the client. 308 * 309 * @param clientState State of the client sending the client request. 310 * @param rRState Maintains the basic state for each request/response 311 * functionality of a client. 312 * @param buf Datagram payload allocated through chppMalloc. Cannot be null. 313 * @param len Datagram length in bytes. 314 * 315 * @return True informs the sender that the datagram was successfully enqueued. 316 * False informs the sender that the payload was discarded because either the 317 * queue was full, or the request timed out. 318 */ 319 bool chppSendTimestampedRequestAndWait(struct ChppClientState *clientState, 320 struct ChppRequestResponseState *rRState, 321 void *buf, size_t len); 322 323 /** 324 * Same as chppSendTimestampedRequestAndWait() but with a specified timeout. 325 */ 326 bool chppSendTimestampedRequestAndWaitTimeout( 327 struct ChppClientState *clientState, 328 struct ChppRequestResponseState *rRState, void *buf, size_t len, 329 uint64_t timeoutNs); 330 331 /** 332 * Markes a closed client as pseudo-open, so that it would be opened upon a 333 * reset. 334 * 335 * @param clientState State variable of the client. 336 */ 337 void chppClientPseudoOpen(struct ChppClientState *clientState); 338 339 /** 340 * Sends a client request for the open command in a blocking or non-blocking 341 * manner. 342 * A non-blocking open is used to for reopening a service after a reset or for 343 * opening a pseudo-open service. 344 * 345 * @param clientState State variable of the client. 346 * @param openRRState Request/response state for the open command. 347 * @param openCommand Open command to be sent. 348 * @param blocking Indicates a blocking (vs. non-blocking) open request. 349 * 350 * @return Indicates success or failure. 351 */ 352 bool chppClientSendOpenRequest(struct ChppClientState *clientState, 353 struct ChppRequestResponseState *openRRState, 354 uint16_t openCommand, bool blocking); 355 356 /** 357 * Processes a service response for the open command. 358 * 359 * @param clientState State variable of the client. 360 */ 361 void chppClientProcessOpenResponse(struct ChppClientState *clientState, 362 uint8_t *buf, size_t len); 363 364 /** 365 * Recalculates the next upcoming client request timeout time. 366 * 367 * @param context Maintains status for each app layer instance. 368 */ 369 void chppClientRecalculateNextTimeout(struct ChppAppState *context); 370 371 /** 372 * Closes any remaining open requests for a given client by sending a timeout. 373 * This function is used when a client is reset. 374 * 375 * @param clientState State variable of the client. 376 * @param client The client for whech to clear out open requests. 377 * @param clearOnly If true, indicates that a timeout response shouldn't be 378 * sent to the client. This must only be set if the requests are being 379 * cleared as part of the client closing. 380 */ 381 void chppClientCloseOpenRequests(struct ChppClientState *clientState, 382 const struct ChppClient *client, 383 bool clearOnly); 384 385 #ifdef __cplusplus 386 } 387 #endif 388 389 #endif // CHPP_CLIENTS_H_ 390