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
chppRegisterCommonServices(struct ChppAppState * context)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
chppDeregisterCommonServices(struct ChppAppState * context)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
chppRegisterService(struct ChppAppState * appContext,void * serviceContext,struct ChppServiceState * serviceState,const struct ChppService * newService)87 void chppRegisterService(struct ChppAppState *appContext, void *serviceContext,
88 struct ChppServiceState *serviceState,
89 const struct ChppService *newService) {
90 CHPP_DEBUG_NOT_NULL(appContext);
91 CHPP_DEBUG_NOT_NULL(serviceContext);
92 CHPP_DEBUG_NOT_NULL(serviceState);
93 CHPP_DEBUG_NOT_NULL(newService);
94
95 const uint8_t numServices = appContext->registeredServiceCount;
96
97 serviceState->openState = CHPP_OPEN_STATE_CLOSED;
98 serviceState->appContext = appContext;
99
100 if (numServices >= CHPP_MAX_REGISTERED_SERVICES) {
101 CHPP_LOGE("Max services registered: # %" PRIu8, numServices);
102 serviceState->handle = CHPP_HANDLE_NONE;
103 return;
104 }
105
106 serviceState->handle = CHPP_SERVICE_HANDLE_OF_INDEX(numServices);
107
108 appContext->registeredServices[numServices] = newService;
109 appContext->registeredServiceContexts[numServices] = serviceContext;
110 appContext->registeredServiceCount++;
111
112 char uuidText[CHPP_SERVICE_UUID_STRING_LEN];
113 chppUuidToStr(newService->descriptor.uuid, uuidText);
114 CHPP_LOGD("Registered service # %" PRIu8
115 " on handle %d"
116 " with name=%s, UUID=%s, version=%" PRIu8 ".%" PRIu8 ".%" PRIu16
117 ", min_len=%" PRIuSIZE " ",
118 numServices, serviceState->handle, newService->descriptor.name,
119 uuidText, newService->descriptor.version.major,
120 newService->descriptor.version.minor,
121 newService->descriptor.version.patch, newService->minLength);
122
123 return;
124 }
125
chppAllocServiceNotification(size_t len)126 struct ChppAppHeader *chppAllocServiceNotification(size_t len) {
127 CHPP_ASSERT(len >= sizeof(struct ChppAppHeader));
128
129 struct ChppAppHeader *result = chppMalloc(len);
130 if (result) {
131 result->handle = CHPP_HANDLE_NONE;
132 result->type = CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION;
133 result->transaction = 0;
134 result->error = CHPP_APP_ERROR_NONE;
135 result->command = CHPP_APP_COMMAND_NONE;
136 }
137 return result;
138 }
139
chppAllocServiceResponse(const struct ChppAppHeader * requestHeader,size_t len)140 struct ChppAppHeader *chppAllocServiceResponse(
141 const struct ChppAppHeader *requestHeader, size_t len) {
142 CHPP_ASSERT(len >= sizeof(struct ChppAppHeader));
143
144 struct ChppAppHeader *result = chppMalloc(len);
145 if (result) {
146 *result = *requestHeader;
147 result->type = CHPP_MESSAGE_TYPE_SERVICE_RESPONSE;
148 result->error = CHPP_APP_ERROR_NONE;
149 }
150 return result;
151 }
152
chppServiceTimestampRequest(struct ChppRequestResponseState * rRState,struct ChppAppHeader * requestHeader)153 void chppServiceTimestampRequest(struct ChppRequestResponseState *rRState,
154 struct ChppAppHeader *requestHeader) {
155 if (rRState->responseTimeNs == CHPP_TIME_NONE &&
156 rRState->requestTimeNs != CHPP_TIME_NONE) {
157 CHPP_LOGE("RX dupe req t=%" PRIu64,
158 rRState->requestTimeNs / CHPP_NSEC_PER_MSEC);
159 }
160 rRState->requestTimeNs = chppGetCurrentTimeNs();
161 rRState->responseTimeNs = CHPP_TIME_NONE;
162 rRState->transaction = requestHeader->transaction;
163 }
164
chppServiceTimestampResponse(struct ChppRequestResponseState * rRState)165 uint64_t chppServiceTimestampResponse(
166 struct ChppRequestResponseState *rRState) {
167 uint64_t previousResponseTime = rRState->responseTimeNs;
168 rRState->responseTimeNs = chppGetCurrentTimeNs();
169 return previousResponseTime;
170 }
171
chppSendTimestampedResponseOrFail(struct ChppServiceState * serviceState,struct ChppRequestResponseState * rRState,void * buf,size_t len)172 bool chppSendTimestampedResponseOrFail(struct ChppServiceState *serviceState,
173 struct ChppRequestResponseState *rRState,
174 void *buf, size_t len) {
175 uint64_t previousResponseTime = chppServiceTimestampResponse(rRState);
176
177 if (rRState->requestTimeNs == CHPP_TIME_NONE) {
178 CHPP_LOGE("TX response w/ no req t=%" PRIu64,
179 rRState->responseTimeNs / CHPP_NSEC_PER_MSEC);
180
181 } else if (previousResponseTime != CHPP_TIME_NONE) {
182 CHPP_LOGW("TX additional response t=%" PRIu64 " for req t=%" PRIu64,
183 rRState->responseTimeNs / CHPP_NSEC_PER_MSEC,
184 rRState->requestTimeNs / CHPP_NSEC_PER_MSEC);
185
186 } else {
187 CHPP_LOGD("Sending initial response at t=%" PRIu64
188 " for request at t=%" PRIu64 " (RTT=%" PRIu64 ")",
189 rRState->responseTimeNs / CHPP_NSEC_PER_MSEC,
190 rRState->requestTimeNs / CHPP_NSEC_PER_MSEC,
191 (rRState->responseTimeNs - rRState->requestTimeNs) /
192 CHPP_NSEC_PER_MSEC);
193 }
194
195 return chppEnqueueTxDatagramOrFail(serviceState->appContext->transportContext,
196 buf, len);
197 }
198