1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <dlfcn.h>
17 #include "hdf_audio_pnp_server.h"
18 #include "audio_uhdf_log.h"
19 #include "hdf_audio_input_event.h"
20 #include "hdf_audio_pnp_uevent.h"
21 #include "hdf_audio_pnp_uevent_hdmi.h"
22 #include "hdf_device_desc.h"
23 #include "hdf_device_object.h"
24 #include "hdf_io_service_if.h"
25 #include "hdf_sbuf.h"
26 #include "hdf_service_status.h"
27 #include "securec.h"
28 #include "servmgr_hdi.h"
29
30 #define HDF_LOG_TAG HDF_AUDIO_HOST
31 #define AUDIO_HDI_SERVICE_NAME "audio_hdi_usb_service"
32 #define AUDIO_TOKEN_SERVER_NAME "ohos.hdi.audio_service"
33 #define AUDIO_PNP_INFO_LEN_MAX 256
34 #define AUDIO_CONTROL "hdf_audio_control"
35
36 #define AUDIODRV_CTRL_IOCTRL_ELEM_HDMI 5 // define from adm control stream id
37
38 struct AudioPnpPriv {
39 void *handle;
40 FfrtAllocBase ffrtAllocBase;
41 FfrtTaskAttrInit ffrtInitAttr;
42 FfrtTaskAttrSetQos ffrtSetQosAttr;
43 FfrtTaskAttrSetName ffrtSetNameAttr;
44 FfrtSubmitBase ffrtSubmitBase;
45 };
46 static struct AudioPnpPriv g_priv;
47
FfrtExecFunctionWrapper(void * t)48 static void FfrtExecFunctionWrapper(void* t)
49 {
50 FfrtFunction* f = (FfrtFunction*)t;
51 if (f == NULL) {
52 return;
53 }
54 if (f->func) {
55 f->func(f->arg);
56 }
57 }
58
FfrtDestroyFunctionWrapper(void * t)59 static void FfrtDestroyFunctionWrapper(void* t)
60 {
61 FfrtFunction* f = (FfrtFunction*)t;
62 if (f == NULL) {
63 return;
64 }
65 if (f->afterFunc) {
66 f->afterFunc(f->arg);
67 }
68 }
69
FfrtCreateFunctionWrapper(const FfrtFunctionT func,const FfrtFunctionT afterFunc,void * arg)70 FfrtFunctionHeader* FfrtCreateFunctionWrapper(const FfrtFunctionT func,
71 const FfrtFunctionT afterFunc, void* arg)
72 {
73 if (sizeof(FfrtFunction) > FFRT_AUTO_MANAGED_FUNCTION_STORAGE_SIZE) {
74 AUDIO_FUNC_LOGE("over memory limit");
75 return NULL;
76 }
77 FfrtFunction* f = (FfrtFunction*)g_priv.ffrtAllocBase(FFRT_FUNCTION_KIND_GENERAL);
78 if (f == NULL) {
79 AUDIO_FUNC_LOGE("ffrt alloc fail");
80 return NULL;
81 }
82 f->header.exec = FfrtExecFunctionWrapper;
83 f->header.destroy = FfrtDestroyFunctionWrapper;
84 f->func = func;
85 f->afterFunc = afterFunc;
86 f->arg = arg;
87 return (FfrtFunctionHeader*)f;
88 }
89
AudioPnpLoadFfrtLib(struct AudioPnpPriv * pPriv)90 static int32_t AudioPnpLoadFfrtLib(struct AudioPnpPriv *pPriv)
91 {
92 char *error = NULL;
93 #ifdef AUDIO_FEATURE_COMMUNITY
94 const char *ffrtLibPath = "/system/lib/chipset-sdk/libffrt.so";
95 #else
96 const char *ffrtLibPath = "/system/lib64/chipset-sdk/libffrt.so";
97 #endif
98 pPriv->handle = dlopen(ffrtLibPath, RTLD_LAZY);
99 if (pPriv->handle == NULL) {
100 error = dlerror();
101 AUDIO_FUNC_LOGE("audio pnp load path%{public}s, dlopen err=%{public}s", ffrtLibPath, error);
102 return HDF_FAILURE;
103 }
104 (void)dlerror(); // clear existing error
105 pPriv->ffrtAllocBase = dlsym(pPriv->handle, "ffrt_alloc_auto_managed_function_storage_base");
106 pPriv->ffrtInitAttr = dlsym(pPriv->handle, "ffrt_task_attr_init");
107 pPriv->ffrtSetQosAttr = dlsym(pPriv->handle, "ffrt_task_attr_set_qos");
108 pPriv->ffrtSetNameAttr = dlsym(pPriv->handle, "ffrt_task_attr_set_name");
109 pPriv->ffrtSubmitBase = dlsym(pPriv->handle, "ffrt_submit_base");
110 if (pPriv->ffrtAllocBase == NULL || pPriv->ffrtInitAttr == NULL || pPriv->ffrtSetQosAttr == NULL
111 || pPriv->ffrtSetNameAttr == NULL || pPriv->ffrtSubmitBase == NULL) {
112 error = dlerror();
113 AUDIO_FUNC_LOGE("dlsym ffrt err=%{public}s", error);
114 dlclose(pPriv->handle);
115 pPriv->handle = NULL;
116 return HDF_FAILURE;
117 }
118 AUDIO_FUNC_LOGD("audio pnp load ffrt lib success");
119 return HDF_SUCCESS;
120 }
121
FfrtAttrInitFunc(void)122 FfrtTaskAttrInit FfrtAttrInitFunc(void)
123 {
124 return g_priv.ffrtInitAttr;
125 }
FfrtAttrSetQosFunc(void)126 FfrtTaskAttrSetQos FfrtAttrSetQosFunc(void)
127 {
128 return g_priv.ffrtSetQosAttr;
129 }
FfrtAttrSetNameFunc(void)130 FfrtTaskAttrSetName FfrtAttrSetNameFunc(void)
131 {
132 return g_priv.ffrtSetNameAttr;
133 }
FfrtSubmitBaseFunc(void)134 FfrtSubmitBase FfrtSubmitBaseFunc(void)
135 {
136 return g_priv.ffrtSubmitBase;
137 }
138
139 static struct HdfDeviceObject *g_audioPnpDevice = NULL;
140
AudioPnpUpdateInfo(const char * statusInfo)141 int32_t AudioPnpUpdateInfo(const char *statusInfo)
142 {
143 if (g_audioPnpDevice == NULL) {
144 AUDIO_FUNC_LOGE("g_audioPnpDevice is null!");
145 return HDF_ERR_INVALID_PARAM;
146 }
147 if (statusInfo == NULL) {
148 AUDIO_FUNC_LOGE("statusInfo is null!");
149 return HDF_ERR_INVALID_PARAM;
150 }
151
152 if (HdfDeviceObjectSetServInfo(g_audioPnpDevice, statusInfo) != HDF_SUCCESS) {
153 AUDIO_FUNC_LOGE("set audio new status info failed!");
154 return HDF_FAILURE;
155 }
156 if (HdfDeviceObjectUpdate(g_audioPnpDevice) != HDF_SUCCESS) {
157 AUDIO_FUNC_LOGE("update audio status info failed!");
158 return HDF_FAILURE;
159 }
160
161 return HDF_SUCCESS;
162 }
163
AudioPnpUpdateInfoOnly(struct AudioEvent audioEvent)164 int32_t AudioPnpUpdateInfoOnly(struct AudioEvent audioEvent)
165 {
166 int32_t ret;
167 char pnpInfo[AUDIO_PNP_INFO_LEN_MAX] = {0};
168
169 ret = snprintf_s(pnpInfo, AUDIO_PNP_INFO_LEN_MAX, AUDIO_PNP_INFO_LEN_MAX - 1, "EVENT_TYPE=%u;DEVICE_TYPE=%u",
170 audioEvent.eventType, audioEvent.deviceType);
171 if (ret < 0) {
172 AUDIO_FUNC_LOGE("snprintf_s failed!");
173 return HDF_FAILURE;
174 }
175
176 ret = AudioPnpUpdateInfo(pnpInfo);
177 if (ret != HDF_SUCCESS) {
178 AUDIO_FUNC_LOGE("Update info failed: ret = %{public}d", ret);
179 return HDF_FAILURE;
180 }
181 AUDIO_FUNC_LOGD("Audio uevent:%{public}s", pnpInfo);
182
183 return HDF_SUCCESS;
184 }
185
HdfAudioPnpBind(struct HdfDeviceObject * device)186 static int32_t HdfAudioPnpBind(struct HdfDeviceObject *device)
187 {
188 AUDIO_FUNC_LOGI("enter.");
189 if (device == NULL) {
190 AUDIO_FUNC_LOGE("device is null!");
191 return HDF_ERR_INVALID_PARAM;
192 }
193 AUDIO_FUNC_LOGI("end.");
194
195 return HDF_SUCCESS;
196 }
197
HdfAudioPnpInit(struct HdfDeviceObject * device)198 static int32_t HdfAudioPnpInit(struct HdfDeviceObject *device)
199 {
200 AUDIO_FUNC_LOGI("enter.");
201 if (device == NULL) {
202 AUDIO_FUNC_LOGE("device is null!");
203 return HDF_ERR_INVALID_PARAM;
204 }
205
206 if (!HdfDeviceSetClass(device, DEVICE_CLASS_AUDIO)) {
207 AUDIO_FUNC_LOGE("set audio class failed!");
208 return HDF_FAILURE;
209 }
210
211 g_audioPnpDevice = device;
212
213 if (AudioPnpLoadFfrtLib(&g_priv) < 0) {
214 AUDIO_FUNC_LOGE("audio pnp load ffrt lib fail");
215 return HDF_FAILURE;
216 }
217
218 AudioUsbPnpUeventStartThread();
219 AudioHeadsetPnpInputStartThread();
220 AudioHdmiPnpUeventStartThread();
221 DetectAudioDevice(device);
222 AUDIO_FUNC_LOGI("end.");
223 return HDF_SUCCESS;
224 }
225
HdfAudioPnpRelease(struct HdfDeviceObject * device)226 static void HdfAudioPnpRelease(struct HdfDeviceObject *device)
227 {
228 AUDIO_FUNC_LOGI("enter.");
229 if (device == NULL) {
230 AUDIO_FUNC_LOGE("device is null!");
231 return;
232 }
233
234 AudioUsbPnpUeventStopThread();
235 AudioHeadsetPnpInputEndThread();
236 AudioHdmiPnpUeventStopThread();
237 device->service = NULL;
238
239 AUDIO_FUNC_LOGI("end.");
240 return;
241 }
242
AudioUhdfUnloadDriver(const char * driverName)243 int32_t AudioUhdfUnloadDriver(const char *driverName)
244 {
245 struct HdfSBuf *sBuf = NULL;
246 struct HdfIoService *service = NULL;
247
248 if (driverName == NULL) {
249 AUDIO_FUNC_LOGE("param is NULL!");
250 return HDF_ERR_INVALID_PARAM;
251 }
252
253 service = HdfIoServiceBind(AUDIO_CONTROL);
254 if (service == NULL || service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
255 AUDIO_FUNC_LOGE("Bind service failed!");
256 return HDF_FAILURE;
257 }
258
259 sBuf = HdfSbufObtainDefaultSize();
260 if (sBuf == NULL) {
261 HdfIoServiceRecycle(service);
262 AUDIO_FUNC_LOGE("sbuf data malloc failed!");
263 return HDF_FAILURE;
264 }
265
266 if (!HdfSbufWriteString(sBuf, driverName)) {
267 HdfSbufRecycle(sBuf);
268 HdfIoServiceRecycle(service);
269 AUDIO_FUNC_LOGE("driverName Write Fail!");
270 return HDF_FAILURE;
271 }
272
273 int32_t ret = service->dispatcher->Dispatch(&service->object, AUDIODRV_CTRL_IOCTRL_ELEM_HDMI, sBuf, NULL);
274 if (ret != HDF_SUCCESS) {
275 HdfSbufRecycle(sBuf);
276 HdfIoServiceRecycle(service);
277 AUDIO_FUNC_LOGE("Unload HDMI Driver dispatch error");
278 return HDF_FAILURE;
279 }
280
281 HdfSbufRecycle(sBuf);
282 HdfIoServiceRecycle(service);
283 return HDF_SUCCESS;
284 }
285
AudioUhdfLoadDriver(const char * driverName)286 int32_t AudioUhdfLoadDriver(const char *driverName)
287 {
288 struct HdfIoService *serv = NULL;
289
290 if (driverName == NULL) {
291 AUDIO_FUNC_LOGE("param is NULL!");
292 return HDF_ERR_INVALID_PARAM;
293 }
294
295 serv = HdfIoServiceBind(driverName);
296 if (serv == NULL) {
297 AUDIO_FUNC_LOGE("error HdfIoServiceBind %{public}s", driverName);
298 return HDF_FAILURE;
299 }
300
301 HdfIoServiceRecycle(serv);
302 return HDF_SUCCESS;
303 }
304
305 struct HdfDriverEntry g_hdiAudioPnpEntry = {
306 .moduleVersion = 1,
307 .moduleName = "hdi_audio_pnp_server",
308 .Bind = HdfAudioPnpBind,
309 .Init = HdfAudioPnpInit,
310 .Release = HdfAudioPnpRelease,
311 };
312
313 HDF_INIT(g_hdiAudioPnpEntry);
314