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 #include "chpp/services.h" 18 19 #include <inttypes.h> 20 #include <stdbool.h> 21 #include <stddef.h> 22 #include <stdint.h> 23 24 #include "chpp/app.h" 25 #include "chpp/log.h" 26 #include "chpp/memory.h" 27 #ifdef CHPP_SERVICE_ENABLED_GNSS 28 #include "chpp/services/gnss.h" 29 #endif 30 #ifdef CHPP_SERVICE_ENABLED_WIFI 31 #include "chpp/services/wifi.h" 32 #endif 33 #ifdef CHPP_SERVICE_ENABLED_WWAN 34 #include "chpp/services/wwan.h" 35 #endif 36 #include "chpp/time.h" 37 #include "chpp/transport.h" 38 39 /************************************************ 40 * Public Functions 41 ***********************************************/ 42 43 void chppRegisterCommonServices(struct ChppAppState *context) { 44 UNUSED_VAR(context); 45 46 #ifdef CHPP_SERVICE_ENABLED_WWAN 47 if (context->clientServiceSet.wwanService) { 48 chppRegisterWwanService(context); 49 } 50 #endif 51 52 #ifdef CHPP_SERVICE_ENABLED_WIFI 53 if (context->clientServiceSet.wifiService) { 54 chppRegisterWifiService(context); 55 } 56 #endif 57 58 #ifdef CHPP_SERVICE_ENABLED_GNSS 59 if (context->clientServiceSet.gnssService) { 60 chppRegisterGnssService(context); 61 } 62 #endif 63 } 64 65 void chppDeregisterCommonServices(struct ChppAppState *context) { 66 UNUSED_VAR(context); 67 68 #ifdef CHPP_SERVICE_ENABLED_WWAN 69 if (context->clientServiceSet.wwanService) { 70 chppDeregisterWwanService(context); 71 } 72 #endif 73 74 #ifdef CHPP_SERVICE_ENABLED_WIFI 75 if (context->clientServiceSet.wifiService) { 76 chppDeregisterWifiService(context); 77 } 78 #endif 79 80 #ifdef CHPP_SERVICE_ENABLED_GNSS 81 if (context->clientServiceSet.gnssService) { 82 chppDeregisterGnssService(context); 83 } 84 #endif 85 } 86 87 uint8_t chppRegisterService(struct ChppAppState *appContext, 88 void *serviceContext, 89 const struct ChppService *newService) { 90 CHPP_NOT_NULL(newService); 91 92 if (appContext->registeredServiceCount >= CHPP_MAX_REGISTERED_SERVICES) { 93 CHPP_LOGE("Max services registered: # %" PRIu8, 94 appContext->registeredServiceCount); 95 return CHPP_HANDLE_NONE; 96 97 } else { 98 appContext->registeredServices[appContext->registeredServiceCount] = 99 newService; 100 appContext->registeredServiceContexts[appContext->registeredServiceCount] = 101 serviceContext; 102 103 char uuidText[CHPP_SERVICE_UUID_STRING_LEN]; 104 chppUuidToStr(newService->descriptor.uuid, uuidText); 105 CHPP_LOGD("Registered service # %" PRIu8 106 " on handle %d" 107 " with name=%s, UUID=%s, version=%" PRIu8 ".%" PRIu8 ".%" PRIu16 108 ", min_len=%" PRIuSIZE " ", 109 appContext->registeredServiceCount, 110 CHPP_SERVICE_HANDLE_OF_INDEX(appContext->registeredServiceCount), 111 newService->descriptor.name, uuidText, 112 newService->descriptor.version.major, 113 newService->descriptor.version.minor, 114 newService->descriptor.version.patch, newService->minLength); 115 116 return CHPP_SERVICE_HANDLE_OF_INDEX(appContext->registeredServiceCount++); 117 } 118 } 119 120 struct ChppAppHeader *chppAllocServiceNotification(size_t len) { 121 CHPP_ASSERT(len >= sizeof(struct ChppAppHeader)); 122 123 struct ChppAppHeader *result = chppMalloc(len); 124 if (result) { 125 result->handle = CHPP_HANDLE_NONE; 126 result->type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION; 127 result->transaction = 0; 128 result->error = CHPP_APP_ERROR_NONE; 129 result->command = CHPP_APP_COMMAND_NONE; 130 } 131 return result; 132 } 133 134 struct ChppAppHeader *chppAllocServiceResponse( 135 const struct ChppAppHeader *requestHeader, size_t len) { 136 CHPP_ASSERT(len >= sizeof(struct ChppAppHeader)); 137 138 struct ChppAppHeader *result = chppMalloc(len); 139 if (result) { 140 *result = *requestHeader; 141 result->type = CHPP_MESSAGE_TYPE_SERVICE_RESPONSE; 142 result->error = CHPP_APP_ERROR_NONE; 143 } 144 return result; 145 } 146 147 void chppServiceTimestampRequest(struct ChppRequestResponseState *rRState, 148 struct ChppAppHeader *requestHeader) { 149 if (rRState->responseTimeNs == CHPP_TIME_NONE && 150 rRState->requestTimeNs != CHPP_TIME_NONE) { 151 CHPP_LOGE("Duplicate request rx at t=%" PRIu64, 152 rRState->requestTimeNs / CHPP_NSEC_PER_MSEC); 153 } 154 rRState->requestTimeNs = chppGetCurrentTimeNs(); 155 rRState->responseTimeNs = CHPP_TIME_NONE; 156 rRState->transaction = requestHeader->transaction; 157 } 158 159 void chppServiceTimestampResponse(struct ChppRequestResponseState *rRState) { 160 uint64_t previousResponseTime = rRState->responseTimeNs; 161 rRState->responseTimeNs = chppGetCurrentTimeNs(); 162 163 if (rRState->requestTimeNs == CHPP_TIME_NONE) { 164 CHPP_LOGE("Tx response w/ no req t=%" PRIu64, 165 rRState->responseTimeNs / CHPP_NSEC_PER_MSEC); 166 167 } else if (previousResponseTime != CHPP_TIME_NONE) { 168 CHPP_LOGW("Resend response t=%" PRIu64 " for request at t=%" PRIu64, 169 rRState->responseTimeNs / CHPP_NSEC_PER_MSEC, 170 rRState->responseTimeNs / CHPP_NSEC_PER_MSEC); 171 172 } else { 173 CHPP_LOGD("Sending initial response at t=%" PRIu64 174 " for request at t=%" PRIu64 " (RTT=%" PRIu64 ")", 175 rRState->responseTimeNs / CHPP_NSEC_PER_MSEC, 176 rRState->responseTimeNs / CHPP_NSEC_PER_MSEC, 177 (rRState->responseTimeNs - rRState->requestTimeNs) / 178 CHPP_NSEC_PER_MSEC); 179 } 180 } 181 182 bool chppSendTimestampedResponseOrFail(struct ChppServiceState *serviceState, 183 struct ChppRequestResponseState *rRState, 184 void *buf, size_t len) { 185 chppServiceTimestampResponse(rRState); 186 return chppEnqueueTxDatagramOrFail(serviceState->appContext->transportContext, 187 buf, len); 188 } 189