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 }