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 State of the app layer. 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 State of the app layer. 138 */ 139 void chppDeregisterCommonClients(struct ChppAppState *context); 140 141 /** 142 * Registers a new client on CHPP. 143 * 144 * This function is to be called by the platform initialization code for every 145 * non-common client available on a server (if any), i.e. except those that are 146 * registered through chppRegisterCommonClients(). 147 * 148 * Registered clients are matched with discovered services during discovery. 149 * When a match succeeds, the client's initialization function (pointer) is 150 * called, assigning them their handle number. 151 * 152 * Note that the maximum number of clients that can be registered on a platform 153 * can specified as CHPP_MAX_REGISTERED_CLIENTS by the initialization code. 154 * Otherwise, a default value will be used. 155 * 156 * @param appContext State of the app layer. 157 * @param clientContext State of the client instance. 158 * @param clientState State variable of the client. 159 * @param rRStates Pointer to array of request-response states, if any. 160 * @param newClient The client to be registered on this platform. 161 */ 162 void chppRegisterClient(struct ChppAppState *appContext, void *clientContext, 163 struct ChppClientState *clientState, 164 struct ChppRequestResponseState *rRStates, 165 const struct ChppClient *newClient); 166 167 /** 168 * Initializes basic CHPP clients. 169 * 170 * @param context State of the app layer. 171 */ 172 void chppInitBasicClients(struct ChppAppState *context); 173 174 /** 175 * Initializes a client. This function must be called when a client is matched 176 * with a service during discovery to provides its handle number. 177 * 178 * @param clientState State variable of the client. 179 * @param handle Handle number for this client. 180 */ 181 void chppClientInit(struct ChppClientState *clientState, uint8_t handle); 182 183 /** 184 * Deinitializes a client. 185 * 186 * @param clientState State variable of the client. 187 */ 188 void chppClientDeinit(struct ChppClientState *clientState); 189 190 /** 191 * Deinitializes basic clients. 192 * 193 * @param context State of the app layer. 194 */ 195 void chppDeinitBasicClients(struct ChppAppState *context); 196 197 /** 198 * Deinitializes all matched clients. 199 * 200 * @param context State of the app layer. 201 */ 202 void chppDeinitMatchedClients(struct ChppAppState *context); 203 204 /** 205 * Allocates a client request message of a specified length, populating the 206 * (app layer) client request header, including the sequence ID. The 207 * next-sequence ID stored in the client state variable is subsequently 208 * incremented. 209 * 210 * It is expected that for most use cases, the chppAllocClientRequestFixed() 211 * or chppAllocClientRequestTypedArray() macros shall be used rather than 212 * calling this function directly. 213 * 214 * @param clientState State variable of the client. 215 * @param len Length of the response message (including header) in bytes. Note 216 * that the specified length must be at least equal to the lendth of the app 217 * layer header. 218 * 219 * @return Pointer to allocated memory 220 */ 221 struct ChppAppHeader *chppAllocClientRequest( 222 struct ChppClientState *clientState, size_t len); 223 224 /** 225 * Uses chppAllocClientRequest() to allocate a specific client request command 226 * without any additional payload. 227 * 228 * @param clientState State variable of the client. 229 * @param command Type of response. 230 * 231 * @return Pointer to allocated memory 232 */ 233 struct ChppAppHeader *chppAllocClientRequestCommand( 234 struct ChppClientState *clientState, uint16_t command); 235 236 /** 237 * This function shall be called for all outgoing client requests in order to 238 * A) Timestamp them, and 239 * B) Save their Transaction ID 240 * as part of the request/response's ChppRequestResponseState struct. 241 * 242 * This function prints an error message if a duplicate request is sent 243 * while outstanding request is still pending without a response. 244 * 245 * @param clientState State of the client sending the client request. 246 * @param transactionId The transaction ID to use when loading the app. 247 * @param rRState Maintains the basic state for each request/response 248 * functionality of a client. 249 * @param requestHeader Client request header. 250 */ 251 void chppClientTimestampRequest(struct ChppClientState *clientState, 252 struct ChppRequestResponseState *rRState, 253 struct ChppAppHeader *requestHeader, 254 uint64_t timeoutNs); 255 256 /** 257 * This function shall be called for incoming responses to a client request in 258 * order to 259 * A) Verify the correct transaction ID 260 * B) Timestamp them, and 261 * C) Mark them as fulfilled 262 * D) TODO: check for timeout 263 * 264 * This function prints an error message if a response is received without an 265 * outstanding request. 266 * 267 * @param clientState State of the client sending the client request. 268 * @param rRState Maintains the basic state for each request/response 269 * functionality of a client. 270 * @param requestHeader Client request header. 271 * 272 * @return false if there is an error. True otherwise. 273 */ 274 bool chppClientTimestampResponse(struct ChppClientState *clientState, 275 struct ChppRequestResponseState *rRState, 276 const struct ChppAppHeader *responseHeader); 277 278 /** 279 * Timestamps a client request using chppClientTimestampResponse() and enqueues 280 * it using chppEnqueueTxDatagramOrFail(). 281 * 282 * Refer to their respective documentation for details. 283 * 284 * Note that the ownership of buf is taken from the caller when this method is 285 * invoked. 286 * 287 * @param clientState State of the client sending the client request. 288 * @param rRState Maintains the basic state for each request/response 289 * functionality of a client. 290 * @param buf Datagram payload allocated through chppMalloc. Cannot be null. 291 * @param len Datagram length in bytes. 292 * @param timeoutNs Time in nanoseconds before a timeout response is generated. 293 * Zero means no timeout response. 294 * 295 * @return True informs the sender that the datagram was successfully enqueued. 296 * False informs the sender that the queue was full and the payload discarded. 297 */ 298 bool chppSendTimestampedRequestOrFail(struct ChppClientState *clientState, 299 struct ChppRequestResponseState *rRState, 300 void *buf, size_t len, 301 uint64_t timeoutNs); 302 303 /** 304 * Similar to chppSendTimestampedRequestOrFail() but blocks execution until a 305 * response is received. Used for synchronous requests. 306 * 307 * In order to use this function, clientState->responseNotifier must have been 308 * initialized using chppNotifierInit() upon initialization of the client. 309 * 310 * @param clientState State of the client sending the client request. 311 * @param rRState Maintains the basic state for each request/response 312 * functionality of a client. 313 * @param buf Datagram payload allocated through chppMalloc. Cannot be null. 314 * @param len Datagram length in bytes. 315 * 316 * @return True informs the sender that the datagram was successfully enqueued. 317 * False informs the sender that the payload was discarded because either the 318 * queue was full, or the request timed out. 319 */ 320 bool chppSendTimestampedRequestAndWait(struct ChppClientState *clientState, 321 struct ChppRequestResponseState *rRState, 322 void *buf, size_t len); 323 324 /** 325 * Same as chppSendTimestampedRequestAndWait() but with a specified timeout. 326 */ 327 bool chppSendTimestampedRequestAndWaitTimeout( 328 struct ChppClientState *clientState, 329 struct ChppRequestResponseState *rRState, void *buf, size_t len, 330 uint64_t timeoutNs); 331 332 /** 333 * Marks a closed client as pseudo-open, so that it would be opened upon a 334 * reset. 335 * 336 * @param clientState State variable of the client. 337 */ 338 void chppClientPseudoOpen(struct ChppClientState *clientState); 339 340 /** 341 * Sends a client request for the open command in a blocking or non-blocking 342 * manner. 343 * A non-blocking open is used to for reopening a service after a reset or for 344 * opening a pseudo-open service. 345 * 346 * @param clientState State variable of the client. 347 * @param openRRState Request/response state for the open command. 348 * @param openCommand Open command to be sent. 349 * @param blocking Indicates a blocking (vs. non-blocking) open request. 350 * 351 * @return Indicates success or failure. 352 */ 353 bool chppClientSendOpenRequest(struct ChppClientState *clientState, 354 struct ChppRequestResponseState *openRRState, 355 uint16_t openCommand, bool blocking); 356 357 /** 358 * Processes a service response for the open command. 359 * 360 * @param clientState State variable of the client. 361 */ 362 void chppClientProcessOpenResponse(struct ChppClientState *clientState, 363 uint8_t *buf, size_t len); 364 365 /** 366 * Recalculates the next upcoming client request timeout time. 367 * 368 * @param context State of the app layer. 369 */ 370 void chppClientRecalculateNextTimeout(struct ChppAppState *context); 371 372 /** 373 * Closes any remaining open requests for a given client by sending a timeout. 374 * This function is used when a client is reset. 375 * 376 * @param clientState State variable of the client. 377 * @param client The client for whech to clear out open requests. 378 * @param clearOnly If true, indicates that a timeout response shouldn't be 379 * sent to the client. This must only be set if the requests are being 380 * cleared as part of the client closing. 381 */ 382 void chppClientCloseOpenRequests(struct ChppClientState *clientState, 383 const struct ChppClient *client, 384 bool clearOnly); 385 386 #ifdef __cplusplus 387 } 388 #endif 389 390 #endif // CHPP_CLIENTS_H_ 391