• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /**
192  * Function type that dispatches incoming datagrams for any client or service
193  */
194 typedef enum ChppAppErrorCode(ChppDispatchFunction)(void *context, uint8_t *buf,
195                                                     size_t len);
196 
197 /**
198  * Function type that initializes a client and assigns it its handle number
199  */
200 typedef bool(ChppClientInitFunction)(void *context, uint8_t handle,
201                                      struct ChppVersion serviceVersion);
202 
203 /**
204  * Function type that deinitializes a client.
205  */
206 typedef void(ChppClientDeinitFunction)(void *context);
207 
208 /**
209  * Function type that dispatches a reset notification to any client or service
210  */
211 typedef void(ChppNotifierFunction)(void *context);
212 
213 /**
214  * Length of a service UUID and its human-readable printed form in bytes
215  */
216 #define CHPP_SERVICE_UUID_LEN 16
217 #define CHPP_SERVICE_UUID_STRING_LEN (16 * 2 + 4 + 1)
218 
219 /**
220  * Length of a version number, in bytes (major + minor + revision), per CHPP
221  * spec.
222  */
223 #define CHPP_SERVICE_VERSION_LEN (1 + 1 + 2)
224 
225 /**
226  * Maximum length of a human-readable service name, per CHPP spec.
227  * (15 ASCII characters + null)
228  */
229 #define CHPP_SERVICE_NAME_MAX_LEN (15 + 1)
230 
231 /**
232  * CHPP definition of a service descriptor as sent over the wire.
233  */
234 CHPP_PACKED_START
235 struct ChppServiceDescriptor {
236   //! UUID of the service.
237   //! Must be generated according to RFC 4122, UUID version 4 (random).
238   uint8_t uuid[CHPP_SERVICE_UUID_LEN];
239 
240   //! Human-readable name of the service for debugging.
241   char name[CHPP_SERVICE_NAME_MAX_LEN];
242 
243   //! Version of the service.
244   struct ChppVersion version;
245 } CHPP_PACKED_ATTR;
246 CHPP_PACKED_END
247 
248 /**
249  * CHPP definition of a service as supported on a server.
250  */
251 struct ChppService {
252   //! Service Descriptor as sent over the wire.
253   struct ChppServiceDescriptor descriptor;
254 
255   //! Pointer to the function that is used to notify the service if CHPP is
256   //! reset.
257   ChppNotifierFunction *resetNotifierFunctionPtr;
258 
259   //! Pointer to the function that dispatches incoming client requests for the
260   //! service.
261   ChppDispatchFunction *requestDispatchFunctionPtr;
262 
263   //! Pointer to the function that dispatches incoming client notifications for
264   //! the service.
265   ChppDispatchFunction *notificationDispatchFunctionPtr;
266 
267   //! Minimum valid length of datagrams for the service.
268   size_t minLength;
269 };
270 
271 /**
272  * CHPP definition of a client descriptor.
273  */
274 struct ChppClientDescriptor {
275   //! UUID of the client.
276   //! Must be generated according to RFC 4122, UUID version 4 (random).
277   uint8_t uuid[CHPP_SERVICE_UUID_LEN];
278 
279   //! Version of the client.
280   struct ChppVersion version;
281 };
282 
283 /**
284  * CHPP definition of a client.
285  */
286 struct ChppClient {
287   //! Client descriptor.
288   struct ChppClientDescriptor descriptor;
289 
290   //! Pointer to the function that is used to notify the client if CHPP is
291   //! reset.
292   ChppNotifierFunction *resetNotifierFunctionPtr;
293 
294   //! Pointer to the function that is used to notify the client if CHPP is
295   //! matched to a service.
296   ChppNotifierFunction *matchNotifierFunctionPtr;
297 
298   //! Pointer to the function that dispatches incoming service responses for the
299   //! client.
300   //! Service responses are only dispatched to clients that have been opened or
301   //! are in the process of being (re)opened. @see ChppOpenState
302   ChppDispatchFunction *responseDispatchFunctionPtr;
303 
304   //! Pointer to the function that dispatches incoming service notifications for
305   //! the client.
306   //! Service notifications are only dispatched to clients that have been
307   //! opened. @see ChppOpenState
308   ChppDispatchFunction *notificationDispatchFunctionPtr;
309 
310   //! Pointer to the function that initializes the client (after it is matched
311   //! with a service at discovery) and assigns it its handle number.
312   ChppClientInitFunction *initFunctionPtr;
313 
314   //! Pointer to the function that deinitializes the client.
315   ChppClientDeinitFunction *deinitFunctionPtr;
316 
317   //! Number of request-response states in the rRStates array. This is a
318   //! uint16_t to match the uint16_t command in struct ChppAppHeader.
319   uint16_t rRStateCount;
320 
321   //! Minimum valid length of datagrams for the service.
322   size_t minLength;
323 };
324 
325 /**
326  * Request status for clients.
327  */
328 enum ChppRequestState {
329   CHPP_REQUEST_STATE_NONE = 0,              // No request sent ever
330   CHPP_REQUEST_STATE_REQUEST_SENT = 1,      // Sent but no response yet
331   CHPP_REQUEST_STATE_RESPONSE_RCV = 2,      // Sent and response received
332   CHPP_REQUEST_STATE_RESPONSE_TIMEOUT = 3,  // Timeout. Responded as need be
333 };
334 
335 /**
336  * Maintains the basic state for each request/response functionality of a
337  * client or service.
338  * Any number of these may be included in the (context) status variable of a
339  * client or service (one per every every request/response functionality).
340  */
341 struct ChppRequestResponseState {
342   uint64_t requestTimeNs;  // Time of the last request
343   uint64_t
344       responseTimeNs;  // If requestState is CHPP_REQUEST_STATE_REQUEST_SENT,
345                        // indicates the timeout time for the request
346                        // If requestState is CHPP_REQUEST_STATE_RESPONSE_RCV,
347                        // indicates when the response was received
348 
349   uint8_t requestState;  // From enum ChppRequestState
350   uint8_t transaction;   // Transaction ID for the last request/response
351 };
352 
353 /**
354  * Enabled clients and services.
355  */
356 struct ChppClientServiceSet {
357   bool wifiService : 1;
358   bool gnssService : 1;
359   bool wwanService : 1;
360   bool wifiClient : 1;
361   bool gnssClient : 1;
362   bool wwanClient : 1;
363   bool loopbackClient : 1;
364 };
365 
366 struct ChppLoopbackClientState;
367 struct ChppTimesyncClientState;
368 
369 struct ChppAppState {
370   struct ChppTransportState *transportContext;  // Pointing to transport context
371 
372   const struct chrePalSystemApi *systemApi;  // Pointing to the PAL system APIs
373 
374   uint8_t registeredServiceCount;  // Number of services currently registered
375 
376   const struct ChppService *registeredServices[CHPP_MAX_REGISTERED_SERVICES];
377 
378   void *registeredServiceContexts[CHPP_MAX_REGISTERED_SERVICES];
379 
380   uint8_t registeredClientCount;  // Number of clients currently registered
381 
382   const struct ChppClient *registeredClients[CHPP_MAX_REGISTERED_CLIENTS];
383 
384   const struct ChppClientState
385       *registeredClientStates[CHPP_MAX_REGISTERED_CLIENTS];
386 
387   void *registeredClientContexts[CHPP_MAX_REGISTERED_CLIENTS];
388 
389   uint64_t nextRequestTimeoutNs;
390 
391   uint8_t
392       clientIndexOfServiceIndex[CHPP_MAX_DISCOVERED_SERVICES];  // Lookup table
393 
394   struct ChppClientServiceSet clientServiceSet;  // Enabled client/services
395 
396   // Pointers to the contexts of basic clients, which are allocated if and when
397   // they are initialized
398   struct ChppLoopbackClientState *loopbackClientContext;
399   struct ChppTimesyncClientState *timesyncClientContext;
400 
401   // For discovery clients
402   bool isDiscoveryClientEverInitialized;
403   bool isDiscoveryClientInitialized;
404   bool isDiscoveryComplete;
405 
406   // The number of clients that matched a service during discovery.
407   uint8_t matchedClientCount;
408 
409   // The number of services that were found during discovery.
410   uint8_t discoveredServiceCount;
411 
412   struct ChppMutex discoveryMutex;
413   struct ChppConditionVariable discoveryCv;
414 };
415 
416 #define CHPP_SERVICE_INDEX_OF_HANDLE(handle) \
417   ((handle)-CHPP_HANDLE_NEGOTIATED_RANGE_START)
418 
419 #define CHPP_SERVICE_HANDLE_OF_INDEX(index) \
420   ((index) + CHPP_HANDLE_NEGOTIATED_RANGE_START)
421 
422 /************************************************
423  *  Public functions
424  ***********************************************/
425 
426 /**
427  * Initializes the CHPP app layer state stored in the parameter appContext.
428  * It is necessary to initialize state for each app layer instance on
429  * every platform.
430  *
431  * @param appContext Maintains status for each app layer instance.
432  * @param transportContext The transport layer status struct associated with
433  * this app layer instance.
434  */
435 void chppAppInit(struct ChppAppState *appContext,
436                  struct ChppTransportState *transportContext);
437 
438 /**
439  * Same as chppAppInit(), but specifies the client/service endpoints to be
440  * enabled.
441  *
442  * @param appContext Maintains status for each app layer instance.
443  * @param transportContext The transport layer status struct associated with
444  * this app layer instance.
445  * @param clientServiceSet Bitmap specifying the client/service endpoints to be
446  * enabled.
447  */
448 void chppAppInitWithClientServiceSet(
449     struct ChppAppState *appContext,
450     struct ChppTransportState *transportContext,
451     struct ChppClientServiceSet clientServiceSet);
452 
453 /**
454  * Deinitializes the CHPP app layer for e.g. clean shutdown.
455  *
456  * @param appContext A non-null pointer to ChppAppState initialized previously
457  * in chppAppInit().
458  */
459 void chppAppDeinit(struct ChppAppState *appContext);
460 
461 /**
462  * Processes an Rx Datagram from the transport layer.
463  *
464  * @param context Maintains status for each app layer instance.
465  * @param buf Input data. Cannot be null.
466  * @param len Length of input data in bytes.
467  */
468 void chppAppProcessRxDatagram(struct ChppAppState *context, uint8_t *buf,
469                               size_t len);
470 
471 /**
472  * Used by the transport layer to notify the app layer of a reset during
473  * operation. This function is called after the transport layer has sent a reset
474  * or reset-ack packet.
475  * In turn, this function notifies clients and services to allow them to reset
476  * or recover state as necessary.
477  *
478  * @param context Maintains status for each app layer instance.
479  */
480 void chppAppProcessReset(struct ChppAppState *context);
481 
482 /**
483  * Convert UUID to a human-readable, null-terminated string.
484  *
485  * @param uuid Input UUID
486  * @param strOut Output null-terminated string
487  */
488 void chppUuidToStr(const uint8_t uuid[CHPP_SERVICE_UUID_LEN],
489                    char strOut[CHPP_SERVICE_UUID_STRING_LEN]);
490 
491 /**
492  * Maps a CHPP app layer error to a CHRE error.
493  *
494  * @param chppError CHPP app layer error (from enum ChppAppErrorCode).
495  *
496  * @return CHRE error (from enum chreError).
497  */
498 uint8_t chppAppErrorToChreError(uint8_t error);
499 
500 /**
501  * Handles logging and error conversion when an app layer response is too short.
502  *
503  * @param buf Input data. Cannot be null.
504  * @param len Length of input data in bytes.
505  * @param responseName Name of the request/response to be logged.
506  *
507  * @return CHRE error (from enum chreError).
508  */
509 uint8_t chppAppShortResponseErrorHandler(uint8_t *buf, size_t len,
510                                          const char *responseName);
511 
512 #ifdef __cplusplus
513 }
514 #endif
515 
516 #endif  // CHPP_APP_H_
517