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,const struct ChppService * newService)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
chppAllocServiceNotification(size_t len)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
chppAllocServiceResponse(const struct ChppAppHeader * requestHeader,size_t len)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
chppServiceTimestampRequest(struct ChppRequestResponseState * rRState,struct ChppAppHeader * requestHeader)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
chppServiceTimestampResponse(struct ChppRequestResponseState * rRState)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
chppSendTimestampedResponseOrFail(struct ChppServiceState * serviceState,struct ChppRequestResponseState * rRState,void * buf,size_t len)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