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