• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 "fake_link_client.h"
18 
19 #include <stdbool.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 #include <string.h>
23 
24 #include "chpp/app.h"
25 #include "chpp/clients.h"
26 #include "chpp/condition_variable.h"
27 #include "chpp/log.h"
28 #include "chpp/macros.h"
29 #include "chpp/mutex.h"
30 #ifdef CHPP_CLIENT_ENABLED_VENDOR
31 #include "chpp/platform/vendor_clients.h"
32 #endif
33 
34 /************************************************
35  *  Prototypes
36  ***********************************************/
37 
38 static bool chppTestClientInit(void *clientContext, uint8_t handle,
39                                struct ChppVersion serviceVersion);
40 static void chppTestClientDeinit(void *clientContext);
41 static void chppTestClientProcessTimeout(void *clientContext);
42 
43 /************************************************
44  *  Private Definitions
45  ***********************************************/
46 
47 #define CHPP_TESTCLIENT_REQUEST_MAX 0
48 
49 /**
50  * Structure to maintain state for the Context client and its Request/Response
51  * (RR) functionality.
52  */
53 struct ChppTestClientState {
54   struct ChppEndpointState client;  // CHPP client state
55   struct ChppOutgoingRequestState outReqStates[CHPP_TESTCLIENT_REQUEST_MAX + 1];
56   bool timeoutPending;
57 };
58 
59 // Note: This global definition of gTestClientContext supports only one
60 // instance of the CHPP Context client at a time.
61 struct ChppTestClientState gTestClientContext;
62 struct ChppConditionVariable gTestClientTimeoutCondition;
63 struct ChppMutex gTestClientTimeoutMutex;
64 
65 /**
66  * Test Client UUID
67  */
68 #define CHPP_UUID_CLIENT_TEST                      \
69   {0x3d, 0x29, 0x78, 0x28, 0x79, 0xf0, 0x4a, 0xad, \
70    0x8f, 0x72, 0x22, 0x15, 0x2f, 0x7d, 0xcc, 0x04}
71 
72 /**
73  * Configuration parameters for this client
74  */
75 static const struct ChppClient kTestClientConfig = {
76     .descriptor.uuid = CHPP_UUID_CLIENT_TEST,
77 
78     // Version
79     .descriptor.version.major = 1,
80     .descriptor.version.minor = 0,
81     .descriptor.version.patch = 0,
82 
83     // Notifies client if CHPP is reset
84     .resetNotifierFunctionPtr = NULL,
85 
86     // Notifies client if they are matched to a service
87     .matchNotifierFunctionPtr = NULL,
88 
89     // Service response dispatch function pointer
90     .responseDispatchFunctionPtr = NULL,
91 
92     // Service notification dispatch function pointer
93     .notificationDispatchFunctionPtr = NULL,
94 
95     // Service response dispatch function pointer
96     .initFunctionPtr = &chppTestClientInit,
97 
98     // Service notification dispatch function pointer
99     .deinitFunctionPtr = &chppTestClientDeinit,
100 
101     // Client timeout function pointer
102     .timeoutFunctionPtr = &chppTestClientProcessTimeout,
103 
104     // Number of request-response states in the outReqStates array.
105     .outReqCount = ARRAY_SIZE(gTestClientContext.outReqStates),
106 
107     // Min length is the entire header
108     .minLength = sizeof(struct ChppAppHeader),
109 };
110 
111 /************************************************
112  *  Private Functions
113  ***********************************************/
114 
chppTestClientInit(void * clientContext,uint8_t handle,struct ChppVersion serviceVersion)115 static bool chppTestClientInit(void *clientContext, uint8_t handle,
116                                struct ChppVersion serviceVersion) {
117   CHPP_LOGI("%s", __func__);
118   UNUSED_VAR(serviceVersion);
119 
120   struct ChppTestClientState *TestClientContext =
121       (struct ChppTestClientState *)clientContext;
122   chppClientInit(&TestClientContext->client, handle);
123 
124   return true;
125 }
126 
127 /**
128  * Deinitializes the client.
129  *
130  * @param clientContext Maintains status for each client instance.
131  */
chppTestClientDeinit(void * clientContext)132 static void chppTestClientDeinit(void *clientContext) {
133   struct ChppTestClientState *TestClientContext =
134       (struct ChppTestClientState *)clientContext;
135   chppClientDeinit(&TestClientContext->client);
136 }
137 
138 /************************************************
139  *  Public Functions
140  ***********************************************/
141 
chppRegisterVendorClients(struct ChppAppState * context)142 void chppRegisterVendorClients(struct ChppAppState *context) {
143   CHPP_DEBUG_NOT_NULL(context);
144 
145   if (context->clientServiceSet.vendorClients) {
146     chppRegisterTestClient(context);
147   }
148 }
149 
chppDeregisterVendorClients(struct ChppAppState * context)150 void chppDeregisterVendorClients(struct ChppAppState *context) {
151   CHPP_DEBUG_NOT_NULL(context);
152 
153   if (context->clientServiceSet.vendorClients) {
154     chppDeregisterTestClient(context);
155   }
156 }
157 
chppRegisterTestClient(struct ChppAppState * appContext)158 void chppRegisterTestClient(struct ChppAppState *appContext) {
159   CHPP_LOGI("%s", __func__);
160   memset(&gTestClientContext, 0, sizeof(gTestClientContext));
161   chppRegisterClient(appContext, (void *)&gTestClientContext,
162                      &gTestClientContext.client,
163                      gTestClientContext.outReqStates, &kTestClientConfig);
164 
165   // Trigger a timeout to test the timeout mechanism
166   chppMutexLock(&gTestClientTimeoutMutex);
167   gTestClientContext.timeoutPending = true;
168   chppAppRequestTimerTimeout(&gTestClientContext.client,
169                              CHPP_TEST_CLIENT_TIMEOUT_MS * CHPP_NSEC_PER_MSEC);
170   chppMutexUnlock(&gTestClientTimeoutMutex);
171 }
172 
chppDeregisterTestClient(struct ChppAppState * appContext)173 void chppDeregisterTestClient(struct ChppAppState *appContext) {
174   CHPP_LOGI("%s", __func__);
175   UNUSED_VAR(appContext);
176 }
177 
chppTestClientProcessTimeout(void * clientContext)178 void chppTestClientProcessTimeout(void *clientContext) {
179   CHPP_LOGI("%s", __func__);
180   UNUSED_VAR(clientContext);
181   chppMutexLock(&gTestClientTimeoutMutex);
182   gTestClientContext.timeoutPending = false;
183   chppConditionVariableSignal(&gTestClientTimeoutCondition);
184   chppMutexUnlock(&gTestClientTimeoutMutex);
185 }
186 
chppTestClientWaitForTimeout(uint64_t timeoutMs)187 bool chppTestClientWaitForTimeout(uint64_t timeoutMs) {
188   bool timeoutTriggered = false;
189   chppMutexLock(&gTestClientTimeoutMutex);
190   if (gTestClientContext.timeoutPending) {
191     chppConditionVariableTimedWait(&gTestClientTimeoutCondition,
192                                    &gTestClientTimeoutMutex,
193                                    timeoutMs * CHPP_NSEC_PER_MSEC);
194   }
195   timeoutTriggered = !gTestClientContext.timeoutPending;
196   chppMutexUnlock(&gTestClientTimeoutMutex);
197   return timeoutTriggered;
198 }
199 
getChppTestClientState(void)200 struct ChppEndpointState *getChppTestClientState(void) {
201   return &gTestClientContext.client;
202 }
203