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_APP_H_
18 #define CHPP_APP_H_
19 
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <stdint.h>
23 
24 #include "chpp/condition_variable.h"
25 #include "chpp/macros.h"
26 #include "chpp/transport.h"
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 /************************************************
33  *  Public Definitions
34  ***********************************************/
35 
36 /**
37  * Maximum number of services that can be registered by CHPP (not including
38  * predefined services), if not defined by the build system.
39  */
40 #ifndef CHPP_MAX_REGISTERED_SERVICES
41 #define CHPP_MAX_REGISTERED_SERVICES 1
42 #endif
43 
44 /**
45  * Maximum number of clients that can be registered by CHPP (not including
46  * predefined clients), if not defined by the build system.
47  */
48 #ifndef CHPP_MAX_REGISTERED_CLIENTS
49 #define CHPP_MAX_REGISTERED_CLIENTS 1
50 #endif
51 
52 /**
53  * Maximum number of services that can be discovered by CHPP (not including
54  * predefined services), if not defined by the build system.
55  */
56 #ifndef CHPP_MAX_DISCOVERED_SERVICES
57 #define CHPP_MAX_DISCOVERED_SERVICES \
58   MAX(CHPP_MAX_REGISTERED_SERVICES, CHPP_MAX_REGISTERED_CLIENTS)
59 #endif
60 
61 /**
62  * Default value for reserved fields.
63  */
64 #define CHPP_RESERVED 0
65 
66 /**
67  * Client index number when there is no matching client
68  */
69 #define CHPP_CLIENT_INDEX_NONE 0xff
70 
71 /**
72  * App layer command at initialization.
73  */
74 #define CHPP_APP_COMMAND_NONE 0
75 
76 /**
77  * Handle Numbers in ChppAppHeader
78  */
79 enum ChppHandleNumber {
80   //! Handleless communication
81   CHPP_HANDLE_NONE = 0x00,
82 
83   //! Loopback Service
84   CHPP_HANDLE_LOOPBACK = 0x01,
85 
86   //! Time Service
87   CHPP_HANDLE_TIMESYNC = 0x02,
88 
89   //! Discovery Service
90   CHPP_HANDLE_DISCOVERY = 0x0F,
91 
92   //! Negotiated Services (starting from this offset)
93   CHPP_HANDLE_NEGOTIATED_RANGE_START = 0x10,
94 };
95 
96 /**
97  * Message Types as used in ChppAppHeader
98  */
99 #define CHPP_APP_MASK_MESSAGE_TYPE LEAST_SIGNIFICANT_NIBBLE
100 #define CHPP_APP_GET_MESSAGE_TYPE(value) \
101   ((enum ChppMessageType)(               \
102       (value)&CHPP_APP_MASK_MESSAGE_TYPE))  // TODO: Consider checking if this
103                                             // maps into a valid enum
104 enum ChppMessageType {
105   //! Request from client. Needs response from service.
106   CHPP_MESSAGE_TYPE_CLIENT_REQUEST = 0,
107 
108   //! Response from service (with the same Command and Transaction ID as the
109   //! client request).
110   CHPP_MESSAGE_TYPE_SERVICE_RESPONSE = 1,
111 
112   //! Notification from client. Service shall not respond.
113   CHPP_MESSAGE_TYPE_CLIENT_NOTIFICATION = 2,
114 
115   //! Notification from service. Client shall not respond.
116   CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION = 3,
117 };
118 
119 /**
120  * Error codes used by the app layer / clients / services.
121  */
122 enum ChppAppErrorCode {
123   //! Success (no error)
124   CHPP_APP_ERROR_NONE = 0,
125   //! Invalid command
126   CHPP_APP_ERROR_INVALID_COMMAND = 1,
127   //! Invalid argument(s)
128   CHPP_APP_ERROR_INVALID_ARG = 2,
129   //! Busy
130   CHPP_APP_ERROR_BUSY = 3,
131   //! Out of memory
132   CHPP_APP_ERROR_OOM = 4,
133   //! Feature not supported
134   CHPP_APP_ERROR_UNSUPPORTED = 5,
135   //! Timeout
136   CHPP_APP_ERROR_TIMEOUT = 6,
137   //! Functionality disabled (e.g. per user configuration)
138   CHPP_APP_ERROR_DISABLED = 7,
139   //! Rate limit exceeded (try again later)
140   CHPP_APP_ERROR_RATELIMITED = 8,
141   //! Function in use / blocked by another entity (e.g. the AP)
142   CHPP_APP_ERROR_BLOCKED = 9,
143   //! Invalid length
144   CHPP_APP_ERROR_INVALID_LENGTH = 10,
145   //! CHPP Not Ready
146   CHPP_APP_ERROR_NOT_READY = 11,
147   //! Error outside of CHPP (e.g. PAL API)
148   CHPP_APP_ERROR_BEYOND_CHPP = 12,
149   //! Response not matching a pending request
150   CHPP_APP_ERROR_UNEXPECTED_RESPONSE = 13,
151   //! Conversion failed
152   CHPP_APP_ERROR_CONVERSION_FAILED = 14,
153   //! Unspecified failure
154   CHPP_APP_ERROR_UNSPECIFIED = 255
155 };
156 
157 /**
158  * Open status for clients / services.
159  */
160 enum ChppOpenState {
161   CHPP_OPEN_STATE_CLOSED = 0,           // Closed
162   CHPP_OPEN_STATE_OPENING = 1,          // Enables the open request to pass
163   CHPP_OPEN_STATE_WAITING_TO_OPEN = 2,  // Waiting for open response
164   CHPP_OPEN_STATE_OPENED = 3,           // Opened
165 };
166 
167 /**
168  * CHPP Application Layer header
169  */
170 CHPP_PACKED_START
171 struct ChppAppHeader {
172   //! Service Handle
173   uint8_t handle;
174 
175   //! Most significant nibble (MSN): Reserved
176   //! Least significant nibble (LSN): Message Type from enum ChppMessageType
177   uint8_t type;
178 
179   //! Transaction ID
180   uint8_t transaction;
181 
182   //! Error if any, from enum ChppAppErrorCode
183   uint8_t error;
184 
185   //! Command
186   uint16_t command;
187 
188 } CHPP_PACKED_ATTR;
189 CHPP_PACKED_END
190 
191 //! Minimum length of a header that includes upto the transaction ID
192 #define CHPP_APP_MIN_LEN_HEADER_WITH_TRANSACTION (3 * sizeof(uint8_t))
193 
194 /**
195  * Function type that dispatches incoming datagrams for any client or service
196  */
197 typedef enum ChppAppErrorCode(ChppDispatchFunction)(void *context, uint8_t *buf,
198                                                     size_t len);
199 
200 /**
201  * Function type that initializes a client and assigns it its handle number
202  */
203 typedef bool(ChppClientInitFunction)(void *context, uint8_t handle,
204                                      struct ChppVersion serviceVersion);
205 
206 /**
207  * Function type that deinitializes a client.
208  */
209 typedef void(ChppClientDeinitFunction)(void *context);
210 
211 /**
212  * Function type that dispatches a reset notification to any client or service
213  */
214 typedef void(ChppNotifierFunction)(void *context);
215 
216 /**
217  * Length of a service UUID and its human-readable printed form in bytes
218  */
219 #define CHPP_SERVICE_UUID_LEN 16
220 #define CHPP_SERVICE_UUID_STRING_LEN (16 * 2 + 4 + 1)
221 
222 /**
223  * Length of a version number, in bytes (major + minor + revision), per CHPP
224  * spec.
225  */
226 #define CHPP_SERVICE_VERSION_LEN (1 + 1 + 2)
227 
228 /**
229  * Maximum length of a human-readable service name, per CHPP spec.
230  * (15 ASCII characters + null)
231  */
232 #define CHPP_SERVICE_NAME_MAX_LEN (15 + 1)
233 
234 /**
235  * CHPP definition of a service descriptor as sent over the wire.
236  */
237 CHPP_PACKED_START
238 struct ChppServiceDescriptor {
239   //! UUID of the service.
240   //! Must be generated according to RFC 4122, UUID version 4 (random).
241   uint8_t uuid[CHPP_SERVICE_UUID_LEN];
242 
243   //! Human-readable name of the service for debugging.
244   char name[CHPP_SERVICE_NAME_MAX_LEN];
245 
246   //! Version of the service.
247   struct ChppVersion version;
248 } CHPP_PACKED_ATTR;
249 CHPP_PACKED_END
250 
251 /**
252  * CHPP definition of a service as supported on a server.
253  */
254 struct ChppService {
255   //! Service Descriptor as sent over the wire.
256   struct ChppServiceDescriptor descriptor;
257 
258   //! Pointer to the function that is used to notify the service if CHPP is
259   //! reset.
260   ChppNotifierFunction *resetNotifierFunctionPtr;
261 
262   //! Pointer to the function that dispatches incoming client requests for the
263   //! service.
264   ChppDispatchFunction *requestDispatchFunctionPtr;
265 
266   //! Pointer to the function that dispatches incoming client notifications for
267   //! the service.
268   ChppDispatchFunction *notificationDispatchFunctionPtr;
269 
270   //! Minimum valid length of datagrams for the service.
271   size_t minLength;
272 };
273 
274 /**
275  * CHPP definition of a client descriptor.
276  */
277 struct ChppClientDescriptor {
278   //! UUID of the client.
279   //! Must be generated according to RFC 4122, UUID version 4 (random).
280   uint8_t uuid[CHPP_SERVICE_UUID_LEN];
281 
282   //! Version of the client.
283   struct ChppVersion version;
284 };
285 
286 /**
287  * CHPP definition of a client.
288  */
289 struct ChppClient {
290   //! Client descriptor.
291   struct ChppClientDescriptor descriptor;
292 
293   //! Pointer to the function that is used to notify the client if CHPP is
294   //! reset.
295   ChppNotifierFunction *resetNotifierFunctionPtr;
296 
297   //! Pointer to the function that is used to notify the client if CHPP is
298   //! matched to a service.
299   ChppNotifierFunction *matchNotifierFunctionPtr;
300 
301   //! Pointer to the function that dispatches incoming service responses for the
302   //! client.
303   //! Service responses are only dispatched to clients that have been opened or
304   //! are in the process of being (re)opened. @see ChppOpenState
305   ChppDispatchFunction *responseDispatchFunctionPtr;
306 
307   //! Pointer to the function that dispatches incoming service notifications for
308   //! the client.
309   //! Service notifications are only dispatched to clients that have been
310   //! opened. @see ChppOpenState
311   ChppDispatchFunction *notificationDispatchFunctionPtr;
312 
313   //! Pointer to the function that initializes the client (after it is matched
314   //! with a service at discovery) and assigns it its handle number.
315   ChppClientInitFunction *initFunctionPtr;
316 
317   //! Pointer to the function that deinitializes the client.
318   ChppClientDeinitFunction *deinitFunctionPtr;
319 
320   //! Number of request-response states in the rRStates array. This is a
321   //! uint16_t to match the uint16_t command in struct ChppAppHeader.
322   uint16_t rRStateCount;
323 
324   //! Minimum valid length of datagrams for the service.
325   size_t minLength;
326 };
327 
328 /**
329  * Request status for clients.
330  */
331 enum ChppRequestState {
332   CHPP_REQUEST_STATE_NONE = 0,              // No request sent ever
333   CHPP_REQUEST_STATE_REQUEST_SENT = 1,      // Sent but no response yet
334   CHPP_REQUEST_STATE_RESPONSE_RCV = 2,      // Sent and response received
335   CHPP_REQUEST_STATE_RESPONSE_TIMEOUT = 3,  // Timeout. Responded as need be
336 };
337 
338 /**
339  * Maintains the basic state for each request/response functionality of a
340  * client or service.
341  * Any number of these may be included in the (context) status variable of a
342  * client or service (one per every every request/response functionality).
343  */
344 struct ChppRequestResponseState {
345   uint64_t requestTimeNs;  // Time of the last request
346   uint64_t
347       responseTimeNs;  // If requestState is CHPP_REQUEST_STATE_REQUEST_SENT,
348                        // indicates the timeout time for the request
349                        // If requestState is CHPP_REQUEST_STATE_RESPONSE_RCV,
350                        // indicates when the response was received
351 
352   uint8_t requestState;  // From enum ChppRequestState
353   uint8_t transaction;   // Transaction ID for the last request/response
354 };
355 
356 /**
357  * Enabled clients and services.
358  */
359 struct ChppClientServiceSet {
360   bool wifiService : 1;
361   bool gnssService : 1;
362   bool wwanService : 1;
363   bool wifiClient : 1;
364   bool gnssClient : 1;
365   bool wwanClient : 1;
366   bool loopbackClient : 1;
367 };
368 
369 struct ChppLoopbackClientState;
370 struct ChppTimesyncClientState;
371 
372 struct ChppAppState {
373   struct ChppTransportState *transportContext;  // Pointing to transport context
374 
375   const struct chrePalSystemApi *systemApi;  // Pointing to the PAL system APIs
376 
377   uint8_t registeredServiceCount;  // Number of services currently registered
378 
379   const struct ChppService *registeredServices[CHPP_MAX_REGISTERED_SERVICES];
380 
381   void *registeredServiceContexts[CHPP_MAX_REGISTERED_SERVICES];
382 
383   uint8_t registeredClientCount;  // Number of clients currently registered
384 
385   const struct ChppClient *registeredClients[CHPP_MAX_REGISTERED_CLIENTS];
386 
387   const struct ChppClientState
388       *registeredClientStates[CHPP_MAX_REGISTERED_CLIENTS];
389 
390   void *registeredClientContexts[CHPP_MAX_REGISTERED_CLIENTS];
391 
392   uint64_t nextRequestTimeoutNs;
393 
394   uint8_t
395       clientIndexOfServiceIndex[CHPP_MAX_DISCOVERED_SERVICES];  // Lookup table
396 
397   struct ChppClientServiceSet clientServiceSet;  // Enabled client/services
398 
399   // Pointers to the contexts of basic clients, which are allocated if and when
400   // they are initialized
401   struct ChppLoopbackClientState *loopbackClientContext;
402   struct ChppTimesyncClientState *timesyncClientContext;
403 
404   // For discovery clients
405   bool isDiscoveryClientEverInitialized;
406   bool isDiscoveryClientInitialized;
407   bool isDiscoveryComplete;
408 
409   // The number of clients that matched a service during discovery.
410   uint8_t matchedClientCount;
411 
412   // The number of services that were found during discovery.
413   uint8_t discoveredServiceCount;
414 
415   struct ChppMutex discoveryMutex;
416   struct ChppConditionVariable discoveryCv;
417 };
418 
419 #define CHPP_SERVICE_INDEX_OF_HANDLE(handle) \
420   ((handle)-CHPP_HANDLE_NEGOTIATED_RANGE_START)
421 
422 #define CHPP_SERVICE_HANDLE_OF_INDEX(index) \
423   ((index) + CHPP_HANDLE_NEGOTIATED_RANGE_START)
424 
425 /************************************************
426  *  Public functions
427  ***********************************************/
428 
429 /**
430  * Initializes the CHPP app layer state stored in the parameter appContext.
431  * It is necessary to initialize state for each app layer instance on
432  * every platform.
433  *
434  * @param appContext Maintains status for each app layer instance.
435  * @param transportContext The transport layer status struct associated with
436  * this app layer instance.
437  */
438 void chppAppInit(struct ChppAppState *appContext,
439                  struct ChppTransportState *transportContext);
440 
441 /**
442  * Same as chppAppInit(), but specifies the client/service endpoints to be
443  * enabled.
444  *
445  * @param appContext Maintains status for each app layer instance.
446  * @param transportContext The transport layer status struct associated with
447  * this app layer instance.
448  * @param clientServiceSet Bitmap specifying the client/service endpoints to be
449  * enabled.
450  */
451 void chppAppInitWithClientServiceSet(
452     struct ChppAppState *appContext,
453     struct ChppTransportState *transportContext,
454     struct ChppClientServiceSet clientServiceSet);
455 
456 /**
457  * Deinitializes the CHPP app layer for e.g. clean shutdown.
458  *
459  * @param appContext A non-null pointer to ChppAppState initialized previously
460  * in chppAppInit().
461  */
462 void chppAppDeinit(struct ChppAppState *appContext);
463 
464 /**
465  * Processes an Rx Datagram from the transport layer.
466  *
467  * @param context Maintains status for each app layer instance.
468  * @param buf Input data. Cannot be null.
469  * @param len Length of input data in bytes.
470  */
471 void chppAppProcessRxDatagram(struct ChppAppState *context, uint8_t *buf,
472                               size_t len);
473 
474 /**
475  * Used by the transport layer to notify the app layer of a reset during
476  * operation. This function is called after the transport layer has sent a reset
477  * or reset-ack packet.
478  * In turn, this function notifies clients and services to allow them to reset
479  * or recover state as necessary.
480  *
481  * @param context Maintains status for each app layer instance.
482  */
483 void chppAppProcessReset(struct ChppAppState *context);
484 
485 /**
486  * Convert UUID to a human-readable, null-terminated string.
487  *
488  * @param uuid Input UUID
489  * @param strOut Output null-terminated string
490  */
491 void chppUuidToStr(const uint8_t uuid[CHPP_SERVICE_UUID_LEN],
492                    char strOut[CHPP_SERVICE_UUID_STRING_LEN]);
493 
494 /**
495  * Maps a CHPP app layer error to a CHRE error.
496  *
497  * @param chppError CHPP app layer error (from enum ChppAppErrorCode).
498  *
499  * @return CHRE error (from enum chreError).
500  */
501 uint8_t chppAppErrorToChreError(uint8_t error);
502 
503 #ifdef __cplusplus
504 }
505 #endif
506 
507 #endif  // CHPP_APP_H_
508