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/macros.h"
27 #include "chpp/memory.h"
28 #include "chpp/mutex.h"
29 #ifdef CHPP_SERVICE_ENABLED_GNSS
30 #include "chpp/services/gnss.h"
31 #endif
32 #ifdef CHPP_SERVICE_ENABLED_WIFI
33 #include "chpp/services/wifi.h"
34 #endif
35 #ifdef CHPP_SERVICE_ENABLED_WWAN
36 #include "chpp/services/wwan.h"
37 #endif
38 #include "chpp/transport.h"
39
40 /************************************************
41 * Public Functions
42 ***********************************************/
43
chppRegisterCommonServices(struct ChppAppState * context)44 void chppRegisterCommonServices(struct ChppAppState *context) {
45 CHPP_DEBUG_NOT_NULL(context);
46 UNUSED_VAR(context);
47
48 #ifdef CHPP_SERVICE_ENABLED_WWAN
49 if (context->clientServiceSet.wwanService) {
50 chppRegisterWwanService(context);
51 }
52 #endif
53
54 #ifdef CHPP_SERVICE_ENABLED_WIFI
55 if (context->clientServiceSet.wifiService) {
56 chppRegisterWifiService(context);
57 }
58 #endif
59
60 #ifdef CHPP_SERVICE_ENABLED_GNSS
61 if (context->clientServiceSet.gnssService) {
62 chppRegisterGnssService(context);
63 }
64 #endif
65 }
66
chppDeregisterCommonServices(struct ChppAppState * context)67 void chppDeregisterCommonServices(struct ChppAppState *context) {
68 CHPP_DEBUG_NOT_NULL(context);
69 UNUSED_VAR(context);
70
71 #ifdef CHPP_SERVICE_ENABLED_WWAN
72 if (context->clientServiceSet.wwanService) {
73 chppDeregisterWwanService(context);
74 }
75 #endif
76
77 #ifdef CHPP_SERVICE_ENABLED_WIFI
78 if (context->clientServiceSet.wifiService) {
79 chppDeregisterWifiService(context);
80 }
81 #endif
82
83 #ifdef CHPP_SERVICE_ENABLED_GNSS
84 if (context->clientServiceSet.gnssService) {
85 chppDeregisterGnssService(context);
86 }
87 #endif
88 }
89
chppRegisterService(struct ChppAppState * appContext,void * serviceContext,struct ChppEndpointState * serviceState,struct ChppOutgoingRequestState * outReqStates,const struct ChppService * newService)90 void chppRegisterService(struct ChppAppState *appContext, void *serviceContext,
91 struct ChppEndpointState *serviceState,
92 struct ChppOutgoingRequestState *outReqStates,
93 const struct ChppService *newService) {
94 CHPP_DEBUG_NOT_NULL(appContext);
95 CHPP_DEBUG_NOT_NULL(serviceContext);
96 CHPP_DEBUG_NOT_NULL(serviceState);
97 CHPP_DEBUG_NOT_NULL(newService);
98
99 const uint8_t numServices = appContext->registeredServiceCount;
100
101 serviceState->openState = CHPP_OPEN_STATE_CLOSED;
102 serviceState->appContext = appContext;
103 serviceState->outReqStates = outReqStates;
104 serviceState->context = serviceContext;
105 serviceState->nextTimerTimeoutNs = CHPP_TIME_MAX;
106
107 if (numServices >= CHPP_MAX_REGISTERED_SERVICES) {
108 CHPP_LOGE("Max services registered: # %" PRIu8, numServices);
109 serviceState->handle = CHPP_HANDLE_NONE;
110 return;
111 }
112
113 serviceState->index = numServices;
114 serviceState->handle = CHPP_SERVICE_HANDLE_OF_INDEX(numServices);
115
116 appContext->registeredServices[numServices] = newService;
117 appContext->registeredServiceStates[numServices] = serviceState;
118 appContext->registeredServiceCount++;
119
120 chppMutexInit(&serviceState->syncResponse.mutex);
121 chppConditionVariableInit(&serviceState->syncResponse.condVar);
122
123 char uuidText[CHPP_SERVICE_UUID_STRING_LEN];
124 chppUuidToStr(newService->descriptor.uuid, uuidText);
125 CHPP_LOGD("Registered service # %" PRIu8
126 " on handle %d"
127 " with name=%s, UUID=%s, version=%" PRIu8 ".%" PRIu8 ".%" PRIu16
128 ", min_len=%" PRIuSIZE " ",
129 numServices, serviceState->handle, newService->descriptor.name,
130 uuidText, newService->descriptor.version.major,
131 newService->descriptor.version.minor,
132 newService->descriptor.version.patch, newService->minLength);
133 }
134
chppAllocServiceNotification(size_t len)135 struct ChppAppHeader *chppAllocServiceNotification(size_t len) {
136 return chppAllocNotification(CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION, len);
137 }
138
chppAllocServiceRequest(struct ChppEndpointState * serviceState,size_t len)139 struct ChppAppHeader *chppAllocServiceRequest(
140 struct ChppEndpointState *serviceState, size_t len) {
141 CHPP_DEBUG_NOT_NULL(serviceState);
142 return chppAllocRequest(CHPP_MESSAGE_TYPE_SERVICE_REQUEST, serviceState, len);
143 }
144
chppAllocServiceRequestCommand(struct ChppEndpointState * serviceState,uint16_t command)145 struct ChppAppHeader *chppAllocServiceRequestCommand(
146 struct ChppEndpointState *serviceState, uint16_t command) {
147 struct ChppAppHeader *request =
148 chppAllocServiceRequest(serviceState, sizeof(struct ChppAppHeader));
149
150 if (request != NULL) {
151 request->command = command;
152 }
153 return request;
154 }
155
chppServiceSendTimestampedRequestOrFail(struct ChppEndpointState * serviceState,struct ChppOutgoingRequestState * outReqState,void * buf,size_t len,uint64_t timeoutNs)156 bool chppServiceSendTimestampedRequestOrFail(
157 struct ChppEndpointState *serviceState,
158 struct ChppOutgoingRequestState *outReqState, void *buf, size_t len,
159 uint64_t timeoutNs) {
160 return chppSendTimestampedRequestOrFail(serviceState, outReqState, buf, len,
161 timeoutNs);
162 }
163
chppServiceSendTimestampedRequestAndWait(struct ChppEndpointState * serviceState,struct ChppOutgoingRequestState * outReqState,void * buf,size_t len)164 bool chppServiceSendTimestampedRequestAndWait(
165 struct ChppEndpointState *serviceState,
166 struct ChppOutgoingRequestState *outReqState, void *buf, size_t len) {
167 return chppServiceSendTimestampedRequestAndWaitTimeout(
168 serviceState, outReqState, buf, len, CHPP_REQUEST_TIMEOUT_DEFAULT);
169 }
170
chppServiceSendTimestampedRequestAndWaitTimeout(struct ChppEndpointState * serviceState,struct ChppOutgoingRequestState * outReqState,void * buf,size_t len,uint64_t timeoutNs)171 bool chppServiceSendTimestampedRequestAndWaitTimeout(
172 struct ChppEndpointState *serviceState,
173 struct ChppOutgoingRequestState *outReqState, void *buf, size_t len,
174 uint64_t timeoutNs) {
175 CHPP_DEBUG_NOT_NULL(serviceState);
176
177 bool result = chppServiceSendTimestampedRequestOrFail(
178 serviceState, outReqState, buf, len, CHPP_REQUEST_TIMEOUT_INFINITE);
179
180 if (!result) {
181 return false;
182 }
183
184 return chppWaitForResponseWithTimeout(&serviceState->syncResponse,
185 outReqState, timeoutNs);
186 }
187
chppServiceCloseOpenRequests(struct ChppEndpointState * serviceState,const struct ChppService * service,bool clearOnly)188 void chppServiceCloseOpenRequests(struct ChppEndpointState *serviceState,
189 const struct ChppService *service,
190 bool clearOnly) {
191 UNUSED_VAR(service);
192 chppCloseOpenRequests(serviceState, CHPP_ENDPOINT_SERVICE, clearOnly);
193 }