/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef CHPP_CLIENTS_H_ #define CHPP_CLIENTS_H_ #include #include #include #include "chpp/app.h" #include "chpp/condition_variable.h" #include "chpp/macros.h" #include "chpp/mutex.h" #include "chre_api/chre/common.h" #ifdef __cplusplus extern "C" { #endif /************************************************ * Public Definitions ***********************************************/ /** * Uses chppAllocClientRequest() to allocate a client request message of a * specific type and its corresponding length. * * @param clientState State variable of the client. * @param type Type of response. * * @return Pointer to allocated memory */ #define chppAllocClientRequestFixed(clientState, type) \ (type *)chppAllocClientRequest(clientState, sizeof(type)) /** * Uses chppAllocClientRequest() to allocate a variable-length client request * message of a specific type. * * @param clientState State variable of the client. * @param type Type of response which includes an arrayed member. * @param count number of items in the array of arrayField. * @param arrayField The arrayed member field. * * @return Pointer to allocated memory */ #define chppAllocClientRequestTypedArray(clientState, type, count, arrayField) \ (type *)chppAllocClientRequest( \ clientState, sizeof(type) + (count)*sizeof_member(type, arrayField[0])) /** * Maintains the basic state of a client. * This is expected to be included once in the (context) status variable of * each client. */ struct ChppClientState { struct ChppAppState *appContext; // Pointer to app layer context struct ChppRequestResponseState *rRStates; // Pointer to array of request-response states, if any uint8_t index; // Index of this client uint8_t handle; // Handle number for this client uint8_t transaction; // Next Transaction ID to be used uint8_t openState; // As defined in enum ChppOpenState bool pseudoOpen : 1; // Client to be opened upon a reset bool initialized : 1; // Is initialized bool everInitialized : 1; // Synchronization primitives initialized bool responseReady : 1; // For sync. request/responses struct ChppMutex responseMutex; struct ChppConditionVariable responseCondVar; }; #ifdef CHPP_CLIENT_ENABLED_CHRE_WWAN #define CHPP_CLIENT_ENABLED_WWAN #endif #ifdef CHPP_CLIENT_ENABLED_CHRE_WIFI #define CHPP_CLIENT_ENABLED_WIFI #endif #ifdef CHPP_CLIENT_ENABLED_CHRE_GNSS #define CHPP_CLIENT_ENABLED_GNSS #endif #if defined(CHPP_CLIENT_ENABLED_LOOPBACK) || \ defined(CHPP_CLIENT_ENABLED_TIMESYNC) || \ defined(CHPP_CLIENT_ENABLED_DISCOVERY) || \ defined(CHPP_CLIENT_ENABLED_WWAN) || defined(CHPP_CLIENT_ENABLED_WIFI) || \ defined(CHPP_CLIENT_ENABLED_GNSS) #define CHPP_CLIENT_ENABLED #endif #define CHPP_CLIENT_REQUEST_TIMEOUT_INFINITE CHPP_TIME_MAX #ifndef CHPP_CLIENT_REQUEST_TIMEOUT_DEFAULT #define CHPP_CLIENT_REQUEST_TIMEOUT_DEFAULT CHRE_ASYNC_RESULT_TIMEOUT_NS #endif // Default timeout for discovery completion. #ifndef CHPP_DISCOVERY_DEFAULT_TIMEOUT_MS #define CHPP_DISCOVERY_DEFAULT_TIMEOUT_MS UINT64_C(10000) // 10s #endif /************************************************ * Public functions ***********************************************/ /** * Registers common clients with the CHPP app layer. These clients are enabled * by CHPP_CLIENT_ENABLED_xxxx definitions. This function is automatically * called by chppAppInit(). * * @param context State of the app layer. */ void chppRegisterCommonClients(struct ChppAppState *context); /** * Deregisters common clients with the CHPP app layer. These clients are enabled * by CHPP_CLIENT_ENABLED_xxxx definitions. This function is automatically * called by chppAppDeinit(). * * @param context State of the app layer. */ void chppDeregisterCommonClients(struct ChppAppState *context); /** * Registers a new client on CHPP. * * This function is to be called by the platform initialization code for every * non-common client available on a server (if any), i.e. except those that are * registered through chppRegisterCommonClients(). * * Registered clients are matched with discovered services during discovery. * When a match succeeds, the client's initialization function (pointer) is * called, assigning them their handle number. * * Note that the maximum number of clients that can be registered on a platform * can specified as CHPP_MAX_REGISTERED_CLIENTS by the initialization code. * Otherwise, a default value will be used. * * @param appContext State of the app layer. * @param clientContext State of the client instance. * @param clientState State variable of the client. * @param rRStates Pointer to array of request-response states, if any. * @param newClient The client to be registered on this platform. */ void chppRegisterClient(struct ChppAppState *appContext, void *clientContext, struct ChppClientState *clientState, struct ChppRequestResponseState *rRStates, const struct ChppClient *newClient); /** * Initializes basic CHPP clients. * * @param context State of the app layer. */ void chppInitBasicClients(struct ChppAppState *context); /** * Initializes a client. This function must be called when a client is matched * with a service during discovery to provides its handle number. * * @param clientState State variable of the client. * @param handle Handle number for this client. */ void chppClientInit(struct ChppClientState *clientState, uint8_t handle); /** * Deinitializes a client. * * @param clientState State variable of the client. */ void chppClientDeinit(struct ChppClientState *clientState); /** * Deinitializes basic clients. * * @param context State of the app layer. */ void chppDeinitBasicClients(struct ChppAppState *context); /** * Deinitializes all matched clients. * * @param context State of the app layer. */ void chppDeinitMatchedClients(struct ChppAppState *context); /** * Allocates a client request message of a specified length, populating the * (app layer) client request header, including the sequence ID. The * next-sequence ID stored in the client state variable is subsequently * incremented. * * It is expected that for most use cases, the chppAllocClientRequestFixed() * or chppAllocClientRequestTypedArray() macros shall be used rather than * calling this function directly. * * @param clientState State variable of the client. * @param len Length of the response message (including header) in bytes. Note * that the specified length must be at least equal to the lendth of the app * layer header. * * @return Pointer to allocated memory */ struct ChppAppHeader *chppAllocClientRequest( struct ChppClientState *clientState, size_t len); /** * Uses chppAllocClientRequest() to allocate a specific client request command * without any additional payload. * * @param clientState State variable of the client. * @param command Type of response. * * @return Pointer to allocated memory */ struct ChppAppHeader *chppAllocClientRequestCommand( struct ChppClientState *clientState, uint16_t command); /** * This function shall be called for all outgoing client requests in order to * A) Timestamp them, and * B) Save their Transaction ID * as part of the request/response's ChppRequestResponseState struct. * * This function prints an error message if a duplicate request is sent * while outstanding request is still pending without a response. * * @param clientState State of the client sending the client request. * @param transactionId The transaction ID to use when loading the app. * @param rRState Maintains the basic state for each request/response * functionality of a client. * @param requestHeader Client request header. */ void chppClientTimestampRequest(struct ChppClientState *clientState, struct ChppRequestResponseState *rRState, struct ChppAppHeader *requestHeader, uint64_t timeoutNs); /** * This function shall be called for incoming responses to a client request in * order to * A) Verify the correct transaction ID * B) Timestamp them, and * C) Mark them as fulfilled * D) TODO: check for timeout * * This function prints an error message if a response is received without an * outstanding request. * * @param clientState State of the client sending the client request. * @param rRState Maintains the basic state for each request/response * functionality of a client. * @param requestHeader Client request header. * * @return false if there is an error. True otherwise. */ bool chppClientTimestampResponse(struct ChppClientState *clientState, struct ChppRequestResponseState *rRState, const struct ChppAppHeader *responseHeader); /** * Timestamps a client request using chppClientTimestampResponse() and enqueues * it using chppEnqueueTxDatagramOrFail(). * * Refer to their respective documentation for details. * * Note that the ownership of buf is taken from the caller when this method is * invoked. * * @param clientState State of the client sending the client request. * @param rRState Maintains the basic state for each request/response * functionality of a client. * @param buf Datagram payload allocated through chppMalloc. Cannot be null. * @param len Datagram length in bytes. * @param timeoutNs Time in nanoseconds before a timeout response is generated. * Zero means no timeout response. * * @return True informs the sender that the datagram was successfully enqueued. * False informs the sender that the queue was full and the payload discarded. */ bool chppSendTimestampedRequestOrFail(struct ChppClientState *clientState, struct ChppRequestResponseState *rRState, void *buf, size_t len, uint64_t timeoutNs); /** * Similar to chppSendTimestampedRequestOrFail() but blocks execution until a * response is received. Used for synchronous requests. * * In order to use this function, clientState->responseNotifier must have been * initialized using chppNotifierInit() upon initialization of the client. * * @param clientState State of the client sending the client request. * @param rRState Maintains the basic state for each request/response * functionality of a client. * @param buf Datagram payload allocated through chppMalloc. Cannot be null. * @param len Datagram length in bytes. * * @return True informs the sender that the datagram was successfully enqueued. * False informs the sender that the payload was discarded because either the * queue was full, or the request timed out. */ bool chppSendTimestampedRequestAndWait(struct ChppClientState *clientState, struct ChppRequestResponseState *rRState, void *buf, size_t len); /** * Same as chppSendTimestampedRequestAndWait() but with a specified timeout. */ bool chppSendTimestampedRequestAndWaitTimeout( struct ChppClientState *clientState, struct ChppRequestResponseState *rRState, void *buf, size_t len, uint64_t timeoutNs); /** * Marks a closed client as pseudo-open, so that it would be opened upon a * reset. * * @param clientState State variable of the client. */ void chppClientPseudoOpen(struct ChppClientState *clientState); /** * Sends a client request for the open command in a blocking or non-blocking * manner. * A non-blocking open is used to for reopening a service after a reset or for * opening a pseudo-open service. * * @param clientState State variable of the client. * @param openRRState Request/response state for the open command. * @param openCommand Open command to be sent. * @param blocking Indicates a blocking (vs. non-blocking) open request. * * @return Indicates success or failure. */ bool chppClientSendOpenRequest(struct ChppClientState *clientState, struct ChppRequestResponseState *openRRState, uint16_t openCommand, bool blocking); /** * Processes a service response for the open command. * * @param clientState State variable of the client. */ void chppClientProcessOpenResponse(struct ChppClientState *clientState, uint8_t *buf, size_t len); /** * Recalculates the next upcoming client request timeout time. * * @param context State of the app layer. */ void chppClientRecalculateNextTimeout(struct ChppAppState *context); /** * Closes any remaining open requests for a given client by sending a timeout. * This function is used when a client is reset. * * @param clientState State variable of the client. * @param client The client for whech to clear out open requests. * @param clearOnly If true, indicates that a timeout response shouldn't be * sent to the client. This must only be set if the requests are being * cleared as part of the client closing. */ void chppClientCloseOpenRequests(struct ChppClientState *clientState, const struct ChppClient *client, bool clearOnly); #ifdef __cplusplus } #endif #endif // CHPP_CLIENTS_H_