1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "audio_control_dispatch.h"
10 #include "audio_control.h"
11 #include "audio_driver_log.h"
12 #include "osal_uaccess.h"
13
14 #define HDF_LOG_TAG HDF_AUDIO_KADM
15 #define MAX_USER_SPACE_SIZE 0x4000
16
AudioGetKctrlInstance(const struct AudioCtrlElemId * ctrlElemId)17 static struct AudioKcontrol *AudioGetKctrlInstance(const struct AudioCtrlElemId *ctrlElemId)
18 {
19 struct AudioKcontrol *kctrl = NULL;
20 struct AudioCard *audioCard = NULL;
21
22 if (ctrlElemId == NULL || ctrlElemId->itemName == NULL || ctrlElemId->cardServiceName == NULL) {
23 ADM_LOG_ERR("input params check error: ctrlElemId is NULL.");
24 return NULL;
25 }
26
27 audioCard = GetCardInstance(ctrlElemId->cardServiceName);
28 if (audioCard == NULL) {
29 ADM_LOG_ERR("get kcontrol instance fail!");
30 return NULL;
31 }
32
33 DLIST_FOR_EACH_ENTRY(kctrl, &audioCard->controls, struct AudioKcontrol, list) {
34 if (kctrl->name == NULL) {
35 continue;
36 }
37 if (strcmp(kctrl->name, ctrlElemId->itemName) != 0) {
38 continue;
39 }
40 if (kctrl->iface != ctrlElemId->iface) {
41 continue;
42 }
43 return kctrl;
44 }
45 return NULL;
46 }
47
ControlHostElemInfoSub(struct HdfSBuf * rspData,const struct AudioCtrlElemId id)48 static int32_t ControlHostElemInfoSub(struct HdfSBuf *rspData, const struct AudioCtrlElemId id)
49 {
50 int32_t result;
51 struct AudioKcontrol *kctrl = NULL;
52 struct AudioCtrlElemInfo elemInfo;
53 if (rspData == NULL) {
54 ADM_LOG_ERR("Input rspData is null.");
55 return HDF_FAILURE;
56 }
57 ADM_LOG_DEBUG("cardName: %s iface: %d itemName: %s .", id.cardServiceName, id.iface, id.itemName);
58 kctrl = AudioGetKctrlInstance(&id);
59 if (kctrl == NULL || kctrl->Info == NULL) {
60 ADM_LOG_ERR("Find kctrl or Info fail!");
61 return HDF_FAILURE;
62 }
63
64 (void)memset_s(&elemInfo, sizeof(struct AudioCtrlElemInfo), 0, sizeof(struct AudioCtrlElemInfo));
65 result = kctrl->Info(kctrl, &elemInfo);
66 if (result != HDF_SUCCESS) {
67 ADM_LOG_ERR("Get control info fail result=%d", result);
68 return HDF_FAILURE;
69 }
70
71 if (!HdfSbufWriteInt32(rspData, elemInfo.type)) {
72 ADM_LOG_ERR("Write response data type failed!");
73 return HDF_FAILURE;
74 }
75 if (!HdfSbufWriteInt32(rspData, elemInfo.max)) {
76 ADM_LOG_ERR("Write response data max failed!");
77 return HDF_FAILURE;
78 }
79 if (!HdfSbufWriteInt32(rspData, elemInfo.min)) {
80 ADM_LOG_ERR("Write response data min failed!");
81 return HDF_FAILURE;
82 }
83 if (!HdfSbufWriteUint32(rspData, elemInfo.count)) {
84 ADM_LOG_ERR("Write response data count failed!");
85 return HDF_FAILURE;
86 }
87 ADM_LOG_DEBUG("success.");
88 return HDF_SUCCESS;
89 }
90
ControlHostElemInfo(const struct HdfDeviceIoClient * client,struct HdfSBuf * reqData,struct HdfSBuf * rspData)91 static int32_t ControlHostElemInfo(const struct HdfDeviceIoClient *client,
92 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
93 {
94 struct AudioCtrlElemId id;
95 ADM_LOG_DEBUG("entry.");
96
97 if (reqData == NULL) {
98 ADM_LOG_ERR("Input ElemInfo params check error: reqData is NULL.");
99 return HDF_FAILURE;
100 }
101 if (client == NULL) {
102 ADM_LOG_ERR("Input ElemInfo params check error: client is NULL.");
103 return HDF_FAILURE;
104 }
105
106 (void)memset_s(&id, sizeof(struct AudioCtrlElemId), 0, sizeof(struct AudioCtrlElemId));
107 if (!HdfSbufReadInt32(reqData, &id.iface)) {
108 ADM_LOG_ERR("Read ElemInfo request id failed!");
109 return HDF_FAILURE;
110 }
111
112 if (!(id.cardServiceName = HdfSbufReadString(reqData))) {
113 ADM_LOG_ERR("Read ElemInfo request cardServiceName failed!");
114 return HDF_FAILURE;
115 }
116
117 if (!(id.itemName = HdfSbufReadString(reqData))) {
118 ADM_LOG_ERR("Read ElemInfo request itemName failed!");
119 return HDF_FAILURE;
120 }
121
122 if (ControlHostElemInfoSub(rspData, id)) {
123 ADM_LOG_ERR("ControlHostElemInfoSub failed!");
124 return HDF_FAILURE;
125 }
126
127 return HDF_SUCCESS;
128 }
129
ControlHostElemRead(const struct HdfDeviceIoClient * client,struct HdfSBuf * reqData,struct HdfSBuf * rspData)130 static int32_t ControlHostElemRead(const struct HdfDeviceIoClient *client, struct HdfSBuf *reqData,
131 struct HdfSBuf *rspData)
132 {
133 struct AudioKcontrol *kctrl = NULL;
134 struct AudioCtrlElemValue elemValue;
135 struct AudioCtrlElemId id;
136 int32_t result;
137
138 if (client == NULL || reqData == NULL || rspData == NULL) {
139 ADM_LOG_ERR("params client or reqData or rspData is null.");
140 return HDF_FAILURE;
141 }
142
143 (void)memset_s(&id, sizeof(struct AudioCtrlElemId), 0, sizeof(struct AudioCtrlElemId));
144 if (!HdfSbufReadInt32(reqData, &id.iface)) {
145 ADM_LOG_ERR("ElemRead request id failed!");
146 return HDF_FAILURE;
147 }
148
149 if (!(id.cardServiceName = HdfSbufReadString(reqData))) {
150 ADM_LOG_ERR("ElemRead request cardServiceName failed!");
151 return HDF_FAILURE;
152 }
153
154 if (!(id.itemName = HdfSbufReadString(reqData))) {
155 ADM_LOG_ERR("ElemRead request itemName failed!");
156 return HDF_FAILURE;
157 }
158 ADM_LOG_DEBUG("itemName: %s cardServiceName: %s iface: %d ", id.itemName, id.cardServiceName, id.iface);
159
160 kctrl = AudioGetKctrlInstance(&id);
161 if (kctrl == NULL || kctrl->Get == NULL) {
162 ADM_LOG_ERR("Find kctrl or Get fail.");
163 return HDF_FAILURE;
164 }
165
166 (void)memset_s(&elemValue, sizeof(struct AudioCtrlElemValue), 0, sizeof(struct AudioCtrlElemValue));
167 result = kctrl->Get(kctrl, &elemValue);
168 if (result != HDF_SUCCESS) {
169 ADM_LOG_ERR("Get elemValue fail result=%d", result);
170 return HDF_FAILURE;
171 }
172
173 if (!HdfSbufWriteInt32(rspData, elemValue.value[0])) {
174 ADM_LOG_ERR("Write response data value[0]=%d failed!", elemValue.value[0]);
175 return HDF_FAILURE;
176 }
177 if (!HdfSbufWriteInt32(rspData, elemValue.value[1])) {
178 ADM_LOG_ERR("Write response data value[1]=%d failed!", elemValue.value[1]);
179 return HDF_FAILURE;
180 }
181 return HDF_SUCCESS;
182 }
183
ControlHostElemWrite(const struct HdfDeviceIoClient * client,struct HdfSBuf * reqData,struct HdfSBuf * rspData)184 static int32_t ControlHostElemWrite(const struct HdfDeviceIoClient *client,
185 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
186 {
187 struct AudioKcontrol *kctrl = NULL;
188 struct AudioCtrlElemValue elemValue;
189 int32_t result;
190
191 if (client == NULL) {
192 ADM_LOG_ERR("Input params check error: client is NULL.");
193 return HDF_FAILURE;
194 }
195 if (reqData == NULL) {
196 ADM_LOG_ERR("Input params check error: reqData is NULL.");
197 return HDF_FAILURE;
198 }
199 (void)rspData;
200
201 (void)memset_s(&elemValue, sizeof(struct AudioCtrlElemValue), 0, sizeof(struct AudioCtrlElemValue));
202 if (!HdfSbufReadInt32(reqData, &elemValue.value[0])) {
203 ADM_LOG_ERR("Read request elemValue failed!");
204 return HDF_FAILURE;
205 }
206 elemValue.value[1] = elemValue.value[0];
207
208 if (!HdfSbufReadInt32(reqData, &elemValue.id.iface)) {
209 ADM_LOG_ERR("Read request id failed!");
210 return HDF_FAILURE;
211 }
212
213 if (!(elemValue.id.cardServiceName = HdfSbufReadString(reqData))) {
214 ADM_LOG_ERR("Read request cardServiceName failed!");
215 return HDF_FAILURE;
216 }
217
218 if (!(elemValue.id.itemName = HdfSbufReadString(reqData))) {
219 ADM_LOG_ERR("Read request itemName failed!");
220 return HDF_FAILURE;
221 }
222
223 ADM_LOG_DEBUG("itemName: %s cardServiceName: %s iface: %d value: %d ", elemValue.id.itemName,
224 elemValue.id.cardServiceName, elemValue.id.iface, elemValue.value[0]);
225
226 kctrl = AudioGetKctrlInstance(&elemValue.id);
227 if (kctrl == NULL || kctrl->Set == NULL) {
228 ADM_LOG_ERR("Find kctrl or Set fail!");
229 return HDF_FAILURE;
230 }
231
232 result = kctrl->Set(kctrl, &elemValue);
233 if (result != HDF_SUCCESS) {
234 ADM_LOG_ERR("Get control value fail result=%d", result);
235 return HDF_FAILURE;
236 }
237 return HDF_SUCCESS;
238 }
239
CodecElemListReqDataDeserialization(struct HdfSBuf * reqData,struct AudioCtlElemList * list,uint64_t * listAddress)240 static int32_t CodecElemListReqDataDeserialization(struct HdfSBuf *reqData, struct AudioCtlElemList *list,
241 uint64_t *listAddress)
242 {
243 if (reqData == NULL || list == NULL) {
244 ADM_LOG_ERR("Input params is NULL.");
245 return HDF_FAILURE;
246 }
247 (void)memset_s(list, sizeof(struct AudioCtlElemList), 0, sizeof(struct AudioCtlElemList));
248
249 list->cardServiceName = HdfSbufReadString(reqData);
250 if (list->cardServiceName == NULL) {
251 ADM_LOG_ERR("Read request cardServiceName failed!");
252 return HDF_FAILURE;
253 }
254
255 if (!HdfSbufReadInt32(reqData, &list->space)) {
256 ADM_LOG_ERR("Read request space failed!");
257 return HDF_FAILURE;
258 }
259
260 if (!HdfSbufReadInt64(reqData, listAddress)) {
261 ADM_LOG_ERR("Read request space failed!");
262 return HDF_FAILURE;
263 }
264
265 if (list->space > MAX_USER_SPACE_SIZE) {
266 ADM_LOG_ERR("list->space(%d) > MAX_USER_SPACE_SIZE!", list->space);
267 return HDF_FAILURE;
268 }
269
270 return HDF_SUCCESS;
271 }
272
CodecSetCtlElemListReportInfo(struct AudioCtlElemList * ctlEleList,struct AudioCtlElemListReport * dst)273 static int32_t CodecSetCtlElemListReportInfo(struct AudioCtlElemList *ctlEleList, struct AudioCtlElemListReport *dst)
274 {
275 struct AudioCard *audioCard = NULL;
276 struct AudioKcontrol *kctrl = NULL;
277
278 if (ctlEleList == NULL || dst == NULL) {
279 ADM_LOG_ERR("Input params is NULL.");
280 return HDF_FAILURE;
281 }
282
283 audioCard = GetCardInstance(ctlEleList->cardServiceName);
284 if (audioCard == NULL) {
285 return HDF_FAILURE;
286 }
287
288 DLIST_FOR_EACH_ENTRY(kctrl, &audioCard->controls, struct AudioKcontrol, list) {
289 if (kctrl->name == NULL) {
290 continue;
291 }
292 if (ctlEleList->count >= ctlEleList->space) {
293 ADM_LOG_ERR("The memory requested by user is too small. user space: %d list count: %d",
294 ctlEleList->space, ctlEleList->count);
295 return HDF_FAILURE;
296 }
297 if (strncpy_s(dst->name, AUDIO_ELEMENT_NAME_LEN, kctrl->name, AUDIO_ELEMENT_NAME_LEN - 1)) {
298 ADM_LOG_ERR("strncpy_s fail!");
299 return HDF_FAILURE;
300 }
301 dst->iface = kctrl->iface;
302 dst++;
303 ctlEleList->count++;
304 }
305
306 return HDF_SUCCESS;
307 }
308
ControlElemListRspDataSerialize(struct HdfSBuf * rspData,struct AudioCtlElemList * ctlEleList)309 static int32_t ControlElemListRspDataSerialize(struct HdfSBuf *rspData, struct AudioCtlElemList *ctlEleList)
310 {
311 if (rspData == NULL || ctlEleList == NULL) {
312 ADM_LOG_ERR("Input params is NULL.");
313 return HDF_FAILURE;
314 }
315
316 if (!HdfSbufWriteString(rspData, ctlEleList->cardServiceName)) {
317 ADM_LOG_ERR("Write response data cardServiceName=%s failed!", ctlEleList->cardServiceName);
318 return HDF_FAILURE;
319 }
320
321 if (!HdfSbufWriteInt32(rspData, ctlEleList->count)) {
322 ADM_LOG_ERR("Write response data list.count=%d failed!", ctlEleList->count);
323 return HDF_FAILURE;
324 }
325
326 if (!HdfSbufWriteInt32(rspData, ctlEleList->space)) {
327 ADM_LOG_ERR("Write response data list.space=%d failed!", ctlEleList->space);
328 return HDF_FAILURE;
329 }
330
331 return HDF_SUCCESS;
332 }
333
ControlHostElemList(const struct HdfDeviceIoClient * client,struct HdfSBuf * reqData,struct HdfSBuf * rspData)334 static int32_t ControlHostElemList(const struct HdfDeviceIoClient *client,
335 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
336 {
337 uint64_t listAddress = 0;
338 struct AudioCtlElemList ctlEleList;
339 struct AudioCtlElemListReport *dst = NULL;
340 int32_t ret;
341
342 if ((client == NULL) || (reqData == NULL) || (rspData == NULL)) {
343 ADM_LOG_ERR("Input params check error: client=%p, reqData=%p, rspData=%p.", client, reqData, rspData);
344 return HDF_FAILURE;
345 }
346
347 if (CodecElemListReqDataDeserialization(reqData, &ctlEleList, &listAddress) != HDF_SUCCESS) {
348 return HDF_FAILURE;
349 }
350
351 dst = (struct AudioCtlElemListReport *)OsalMemCalloc(ctlEleList.space * sizeof(struct AudioCtlElemListReport));
352 if (dst == NULL) {
353 ADM_LOG_ERR("Malloc dst fail!");
354 return HDF_ERR_MALLOC_FAIL;
355 }
356
357 ctlEleList.count = 0;
358 ret = CodecSetCtlElemListReportInfo(&ctlEleList, dst);
359 if (ret != HDF_SUCCESS) {
360 ADM_LOG_ERR("CodecSetCtlElemListReportInfo fail!");
361 OsalMemFree(dst);
362 return HDF_FAILURE;
363 }
364
365 ret = ControlElemListRspDataSerialize(rspData, &ctlEleList);
366 if (ret != HDF_SUCCESS) {
367 ADM_LOG_ERR("ControlElemListRspDataSerialize fail!");
368 OsalMemFree(dst);
369 return HDF_FAILURE;
370 }
371
372 if (CopyToUser((char *)listAddress, (char *)(dst), ctlEleList.count * sizeof(struct AudioCtlElemListReport)) != 0) {
373 AUDIO_DRIVER_LOG_ERR("CopyToUser failed.");
374 OsalMemFree(dst);
375 return HDF_FAILURE;
376 }
377
378 OsalMemFree(dst);
379 return HDF_SUCCESS;
380 }
381
382 static struct ControlDispCmdHandleList g_controlDispCmdHandle[] = {
383 {AUDIODRV_CTRL_IOCTRL_ELEM_INFO, ControlHostElemInfo},
384 {AUDIODRV_CTRL_IOCTRL_ELEM_READ, ControlHostElemRead},
385 {AUDIODRV_CTRL_IOCTRL_ELEM_WRITE, ControlHostElemWrite},
386 {AUDIODRV_CTRL_IOCTRL_ELEM_LIST, ControlHostElemList},
387 };
388
ControlDispatch(struct HdfDeviceIoClient * client,int32_t cmdId,struct HdfSBuf * data,struct HdfSBuf * reply)389 static int32_t ControlDispatch(struct HdfDeviceIoClient *client, int32_t cmdId,
390 struct HdfSBuf *data, struct HdfSBuf *reply)
391 {
392 uint32_t i;
393
394 if (client == NULL) {
395 ADM_LOG_ERR("Input params check error: client is NULL.");
396 return HDF_FAILURE;
397 }
398 if (data == NULL) {
399 ADM_LOG_ERR("Input params check error: data is NULL.");
400 return HDF_FAILURE;
401 }
402
403 if (cmdId >= AUDIODRV_CTRL_IOCTRL_ELEM_BUTT || cmdId < 0) {
404 ADM_LOG_ERR("Invalid [cmdId=%d].", cmdId);
405 return HDF_FAILURE;
406 }
407
408 for (i = 0; i < HDF_ARRAY_SIZE(g_controlDispCmdHandle); ++i) {
409 if ((cmdId == (int32_t)(g_controlDispCmdHandle[i].cmd)) && (g_controlDispCmdHandle[i].func != NULL)) {
410 return g_controlDispCmdHandle[i].func(client, data, reply);
411 }
412 }
413 return HDF_FAILURE;
414 }
415
ControlHostCreateAndBind(struct HdfDeviceObject * device)416 static struct ControlHost *ControlHostCreateAndBind(struct HdfDeviceObject *device)
417 {
418 struct ControlHost *controlHost = NULL;
419
420 if (device == NULL) {
421 ADM_LOG_ERR("Input params check error: device is NULL.");
422 return NULL;
423 }
424
425 controlHost = (struct ControlHost *)OsalMemCalloc(sizeof(*controlHost));
426 if (controlHost == NULL) {
427 ADM_LOG_ERR("Malloc controlHost fail!");
428 return NULL;
429 }
430 controlHost->device = device;
431 device->service = &controlHost->service;
432 return controlHost;
433 }
434
AudioControlBind(struct HdfDeviceObject * device)435 static int32_t AudioControlBind(struct HdfDeviceObject *device)
436 {
437 struct ControlHost *controlHost = NULL;
438 ADM_LOG_DEBUG("entry.");
439
440 if (device == NULL) {
441 ADM_LOG_ERR("Input params check error: device is NULL.");
442 return HDF_FAILURE;
443 }
444
445 controlHost = ControlHostCreateAndBind(device);
446 if (controlHost == NULL) {
447 ADM_LOG_ERR("controlHost is NULL.");
448 return HDF_FAILURE;
449 }
450
451 controlHost->service.Dispatch = ControlDispatch;
452
453 ADM_LOG_INFO("success.");
454 return HDF_SUCCESS;
455 }
456
AudioControlInit(struct HdfDeviceObject * device)457 static int32_t AudioControlInit(struct HdfDeviceObject *device)
458 {
459 (void)device;
460 ADM_LOG_INFO("success.");
461 return HDF_SUCCESS;
462 }
463
AudioControlRelease(struct HdfDeviceObject * device)464 static void AudioControlRelease(struct HdfDeviceObject *device)
465 {
466 struct ControlHost *controlHost = NULL;
467
468 if (device == NULL) {
469 ADM_LOG_ERR("Input params check error: device is NULL.");
470 return;
471 }
472
473 controlHost = (struct ControlHost *)device->service;
474 if (controlHost == NULL) {
475 ADM_LOG_ERR("controlHost is NULL.");
476 return;
477 }
478 OsalMemFree(controlHost);
479 }
480
481 /* HdfDriverEntry definitions */
482 struct HdfDriverEntry g_audioControlEntry = {
483 .moduleVersion = 1,
484 .moduleName = "HDF_AUDIO_CONTROL",
485 .Bind = AudioControlBind,
486 .Init = AudioControlInit,
487 .Release = AudioControlRelease,
488 };
489 HDF_INIT(g_audioControlEntry);
490