• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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