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