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
106 if (numServices >= CHPP_MAX_REGISTERED_SERVICES) {
107 CHPP_LOGE("Max services registered: # %" PRIu8, numServices);
108 serviceState->handle = CHPP_HANDLE_NONE;
109 return;
110 }
111
112 serviceState->index = numServices;
113 serviceState->handle = CHPP_SERVICE_HANDLE_OF_INDEX(numServices);
114
115 appContext->registeredServices[numServices] = newService;
116 appContext->registeredServiceStates[numServices] = serviceState;
117 appContext->registeredServiceCount++;
118
119 chppMutexInit(&serviceState->syncResponse.mutex);
120 chppConditionVariableInit(&serviceState->syncResponse.condVar);
121
122 char uuidText[CHPP_SERVICE_UUID_STRING_LEN];
123 chppUuidToStr(newService->descriptor.uuid, uuidText);
124 CHPP_LOGD("Registered service # %" PRIu8
125 " on handle %d"
126 " with name=%s, UUID=%s, version=%" PRIu8 ".%" PRIu8 ".%" PRIu16
127 ", min_len=%" PRIuSIZE " ",
128 numServices, serviceState->handle, newService->descriptor.name,
129 uuidText, newService->descriptor.version.major,
130 newService->descriptor.version.minor,
131 newService->descriptor.version.patch, newService->minLength);
132 }
133
chppAllocServiceNotification(size_t len)134 struct ChppAppHeader *chppAllocServiceNotification(size_t len) {
135 return chppAllocNotification(CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION, len);
136 }
137
chppAllocServiceRequest(struct ChppEndpointState * serviceState,size_t len)138 struct ChppAppHeader *chppAllocServiceRequest(
139 struct ChppEndpointState *serviceState, size_t len) {
140 CHPP_DEBUG_NOT_NULL(serviceState);
141 return chppAllocRequest(CHPP_MESSAGE_TYPE_SERVICE_REQUEST, serviceState, len);
142 }
143
chppAllocServiceRequestCommand(struct ChppEndpointState * serviceState,uint16_t command)144 struct ChppAppHeader *chppAllocServiceRequestCommand(
145 struct ChppEndpointState *serviceState, uint16_t command) {
146 struct ChppAppHeader *request =
147 chppAllocServiceRequest(serviceState, sizeof(struct ChppAppHeader));
148
149 if (request != NULL) {
150 request->command = command;
151 }
152 return request;
153 }
154
chppServiceSendTimestampedRequestOrFail(struct ChppEndpointState * serviceState,struct ChppOutgoingRequestState * outReqState,void * buf,size_t len,uint64_t timeoutNs)155 bool chppServiceSendTimestampedRequestOrFail(
156 struct ChppEndpointState *serviceState,
157 struct ChppOutgoingRequestState *outReqState, void *buf, size_t len,
158 uint64_t timeoutNs) {
159 return chppSendTimestampedRequestOrFail(serviceState, outReqState, buf, len,
160 timeoutNs);
161 }
162
chppServiceSendTimestampedRequestAndWait(struct ChppEndpointState * serviceState,struct ChppOutgoingRequestState * outReqState,void * buf,size_t len)163 bool chppServiceSendTimestampedRequestAndWait(
164 struct ChppEndpointState *serviceState,
165 struct ChppOutgoingRequestState *outReqState, void *buf, size_t len) {
166 return chppServiceSendTimestampedRequestAndWaitTimeout(
167 serviceState, outReqState, buf, len, CHPP_REQUEST_TIMEOUT_DEFAULT);
168 }
169
chppServiceSendTimestampedRequestAndWaitTimeout(struct ChppEndpointState * serviceState,struct ChppOutgoingRequestState * outReqState,void * buf,size_t len,uint64_t timeoutNs)170 bool chppServiceSendTimestampedRequestAndWaitTimeout(
171 struct ChppEndpointState *serviceState,
172 struct ChppOutgoingRequestState *outReqState, void *buf, size_t len,
173 uint64_t timeoutNs) {
174 CHPP_DEBUG_NOT_NULL(serviceState);
175
176 bool result = chppServiceSendTimestampedRequestOrFail(
177 serviceState, outReqState, buf, len, CHPP_REQUEST_TIMEOUT_INFINITE);
178
179 if (!result) {
180 return false;
181 }
182
183 return chppWaitForResponseWithTimeout(&serviceState->syncResponse,
184 outReqState, timeoutNs);
185 }
186
chppServiceCloseOpenRequests(struct ChppEndpointState * serviceState,const struct ChppService * service,bool clearOnly)187 void chppServiceCloseOpenRequests(struct ChppEndpointState *serviceState,
188 const struct ChppService *service,
189 bool clearOnly) {
190 UNUSED_VAR(service);
191 chppCloseOpenRequests(serviceState, CHPP_ENDPOINT_SERVICE, clearOnly);
192 }