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
13 #define HDF_LOG_TAG audio_control_dispatch
14
AudioGetKctrlInstance(const struct AudioCtrlElemId * ctrlElemId)15 static struct AudioKcontrol *AudioGetKctrlInstance(const struct AudioCtrlElemId *ctrlElemId)
16 {
17 struct AudioKcontrol *kctrl = NULL;
18 struct AudioCard *audioCard = NULL;
19
20 if (ctrlElemId == NULL || ctrlElemId->itemName == NULL || ctrlElemId->cardServiceName == NULL) {
21 ADM_LOG_ERR("input params check error: ctrlElemId is NULL.");
22 return NULL;
23 }
24
25 audioCard = GetCardInstance(ctrlElemId->cardServiceName);
26 if (audioCard == NULL) {
27 ADM_LOG_ERR("get kcontrol instance fail!");
28 return NULL;
29 }
30
31 DLIST_FOR_EACH_ENTRY(kctrl, &audioCard->controls, struct AudioKcontrol, list) {
32 if (kctrl->name == NULL) {
33 continue;
34 }
35 if (strcmp(kctrl->name, ctrlElemId->itemName) != 0) {
36 continue;
37 }
38 if (kctrl->iface != ctrlElemId->iface) {
39 continue;
40 }
41 return kctrl;
42 }
43 return NULL;
44 }
45
ControlHostElemInfoSub(struct HdfSBuf * rspData,const struct AudioCtrlElemId id)46 static int32_t ControlHostElemInfoSub(struct HdfSBuf *rspData, const struct AudioCtrlElemId id)
47 {
48 int32_t result;
49 struct AudioKcontrol *kctrl = NULL;
50 struct AudioCtrlElemInfo elemInfo;
51 if (rspData == NULL) {
52 ADM_LOG_ERR("Input rspData is null.");
53 return HDF_FAILURE;
54 }
55 kctrl = AudioGetKctrlInstance(&id);
56 if (kctrl == NULL || kctrl->Info == NULL) {
57 ADM_LOG_ERR("Find kctrl or Info fail!");
58 return HDF_FAILURE;
59 }
60
61 (void)memset_s(&elemInfo, sizeof(struct AudioCtrlElemInfo), 0, sizeof(struct AudioCtrlElemInfo));
62 result = kctrl->Info(kctrl, &elemInfo);
63 if (result != HDF_SUCCESS) {
64 ADM_LOG_ERR("Get control info fail result=%d", result);
65 return HDF_FAILURE;
66 }
67
68 if (!HdfSbufWriteInt32(rspData, elemInfo.type)) {
69 ADM_LOG_ERR("Write response data type failed!");
70 return HDF_FAILURE;
71 }
72 if (!HdfSbufWriteInt32(rspData, elemInfo.max)) {
73 ADM_LOG_ERR("Write response data max failed!");
74 return HDF_FAILURE;
75 }
76 if (!HdfSbufWriteInt32(rspData, elemInfo.min)) {
77 ADM_LOG_ERR("Write response data min failed!");
78 return HDF_FAILURE;
79 }
80 if (!HdfSbufWriteUint32(rspData, elemInfo.count)) {
81 ADM_LOG_ERR("Write response data count failed!");
82 return HDF_FAILURE;
83 }
84 ADM_LOG_DEBUG("success.");
85 return HDF_SUCCESS;
86 }
87
ControlHostElemInfo(const struct HdfDeviceIoClient * client,struct HdfSBuf * reqData,struct HdfSBuf * rspData)88 static int32_t ControlHostElemInfo(const struct HdfDeviceIoClient *client,
89 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
90 {
91 struct AudioCtrlElemId id;
92 ADM_LOG_DEBUG("entry.");
93
94 if ((client == NULL) || (reqData == NULL)) {
95 ADM_LOG_ERR("Input ElemInfo params check error: client=%p, reqData=%p.", client, reqData);
96 return HDF_FAILURE;
97 }
98
99 (void)memset_s(&id, sizeof(struct AudioCtrlElemId), 0, sizeof(struct AudioCtrlElemId));
100 if (!HdfSbufReadInt32(reqData, &id.iface)) {
101 ADM_LOG_ERR("Read ElemInfo request id failed!");
102 return HDF_FAILURE;
103 }
104
105 if (!(id.cardServiceName = HdfSbufReadString(reqData))) {
106 ADM_LOG_ERR("Read ElemInfo request cardServiceName failed!");
107 return HDF_FAILURE;
108 }
109
110 if (!(id.itemName = HdfSbufReadString(reqData))) {
111 ADM_LOG_ERR("Read ElemInfo request itemName failed!");
112 return HDF_FAILURE;
113 }
114
115 if (ControlHostElemInfoSub(rspData, id)) {
116 ADM_LOG_ERR("ControlHostElemInfoSub failed!");
117 return HDF_FAILURE;
118 }
119
120 return HDF_SUCCESS;
121 }
122
ControlHostElemRead(const struct HdfDeviceIoClient * client,struct HdfSBuf * reqData,struct HdfSBuf * rspData)123 static int32_t ControlHostElemRead(const struct HdfDeviceIoClient *client, struct HdfSBuf *reqData,
124 struct HdfSBuf *rspData)
125 {
126 struct AudioKcontrol *kctrl = NULL;
127 struct AudioCtrlElemValue elemValue;
128 struct AudioCtrlElemId id;
129 int32_t result;
130
131 if ((client == NULL) || (reqData == NULL) || (rspData == NULL)) {
132 ADM_LOG_ERR("Input ElemRead params check error: client=%p, reqData=%p, rspData=%p.", client, reqData, rspData);
133 return HDF_FAILURE;
134 }
135
136 (void)memset_s(&id, sizeof(struct AudioCtrlElemId), 0, sizeof(struct AudioCtrlElemId));
137 if (!HdfSbufReadInt32(reqData, &id.iface)) {
138 ADM_LOG_ERR("ElemRead request id failed!");
139 return HDF_FAILURE;
140 }
141
142 if (!(id.cardServiceName = HdfSbufReadString(reqData))) {
143 ADM_LOG_ERR("ElemRead request cardServiceName failed!");
144 return HDF_FAILURE;
145 }
146
147 if (!(id.itemName = HdfSbufReadString(reqData))) {
148 ADM_LOG_ERR("ElemRead request itemName failed!");
149 return HDF_FAILURE;
150 }
151 ADM_LOG_DEBUG("itemName: %s cardServiceName: %s iface: %d ", id.itemName, id.cardServiceName, id.iface);
152
153 kctrl = AudioGetKctrlInstance(&id);
154 if (kctrl == NULL || kctrl->Get == NULL) {
155 ADM_LOG_ERR("Find kctrl or Get fail.");
156 return HDF_FAILURE;
157 }
158
159 (void)memset_s(&elemValue, sizeof(struct AudioCtrlElemValue), 0, sizeof(struct AudioCtrlElemValue));
160 result = kctrl->Get(kctrl, &elemValue);
161 if (result != HDF_SUCCESS) {
162 ADM_LOG_ERR("Get elemValue fail result=%d", result);
163 return HDF_FAILURE;
164 }
165
166 if (!HdfSbufWriteInt32(rspData, elemValue.value[0])) {
167 ADM_LOG_ERR("Write response data value[0]=%d failed!", elemValue.value[0]);
168 return HDF_FAILURE;
169 }
170 if (!HdfSbufWriteInt32(rspData, elemValue.value[1])) {
171 ADM_LOG_ERR("Write response data value[1]=%d failed!", elemValue.value[1]);
172 return HDF_FAILURE;
173 }
174 return HDF_SUCCESS;
175 }
176
ControlHostElemWrite(const struct HdfDeviceIoClient * client,struct HdfSBuf * reqData,struct HdfSBuf * rspData)177 static int32_t ControlHostElemWrite(const struct HdfDeviceIoClient *client,
178 struct HdfSBuf *reqData, struct HdfSBuf *rspData)
179 {
180 struct AudioKcontrol *kctrl = NULL;
181 struct AudioCtrlElemValue elemValue;
182 int32_t result;
183
184 if ((client == NULL) || (reqData == NULL)) {
185 ADM_LOG_ERR("Input params check error: client=%p, reqData=%p.", client, reqData);
186 return HDF_FAILURE;
187 }
188 (void)rspData;
189
190 (void)memset_s(&elemValue, sizeof(struct AudioCtrlElemValue), 0, sizeof(struct AudioCtrlElemValue));
191 if (!HdfSbufReadInt32(reqData, &elemValue.value[0])) {
192 ADM_LOG_ERR("Read request elemValue failed!");
193 return HDF_FAILURE;
194 }
195 elemValue.value[1] = elemValue.value[0];
196
197 if (!HdfSbufReadInt32(reqData, &elemValue.id.iface)) {
198 ADM_LOG_ERR("Read request id failed!");
199 return HDF_FAILURE;
200 }
201
202 if (!(elemValue.id.cardServiceName = HdfSbufReadString(reqData))) {
203 ADM_LOG_ERR("Read request cardServiceName failed!");
204 return HDF_FAILURE;
205 }
206
207 if (!(elemValue.id.itemName = HdfSbufReadString(reqData))) {
208 ADM_LOG_ERR("Read request itemName failed!");
209 return HDF_FAILURE;
210 }
211
212 ADM_LOG_DEBUG("itemName: %s cardServiceName: %s iface: %d value: %d ", elemValue.id.itemName,
213 elemValue.id.cardServiceName,
214 elemValue.id.iface, elemValue.value[0]);
215
216 kctrl = AudioGetKctrlInstance(&elemValue.id);
217 if (kctrl == NULL || kctrl->Set == NULL) {
218 ADM_LOG_ERR("Find kctrl or Set fail!");
219 return HDF_FAILURE;
220 }
221
222 result = kctrl->Set(kctrl, &elemValue);
223 if (result != HDF_SUCCESS) {
224 ADM_LOG_ERR("Get control value fail result=%d", result);
225 return HDF_FAILURE;
226 }
227 return HDF_SUCCESS;
228 }
229
230 static struct ControlDispCmdHandleList g_controlDispCmdHandle[] = {
231 {AUDIODRV_CTRL_IOCTRL_ELEM_INFO, ControlHostElemInfo},
232 {AUDIODRV_CTRL_IOCTRL_ELEM_READ, ControlHostElemRead},
233 {AUDIODRV_CTRL_IOCTRL_ELEM_WRITE, ControlHostElemWrite},
234 };
235
ControlDispatch(struct HdfDeviceIoClient * client,int cmdId,struct HdfSBuf * data,struct HdfSBuf * reply)236 static int32_t ControlDispatch(struct HdfDeviceIoClient *client, int cmdId,
237 struct HdfSBuf *data, struct HdfSBuf *reply)
238 {
239 unsigned int i;
240
241 if ((client == NULL) || (data == NULL)) {
242 ADM_LOG_ERR("Input params check error: client=%p, data=%p.", client, data);
243 return HDF_FAILURE;
244 }
245
246 if (cmdId >= AUDIODRV_CTRL_IOCTRL_ELEM_BUTT || cmdId < 0) {
247 ADM_LOG_ERR("Invalid [cmdId=%d].", cmdId);
248 return HDF_FAILURE;
249 }
250
251 for (i = 0; i < HDF_ARRAY_SIZE(g_controlDispCmdHandle); ++i) {
252 if ((cmdId == (int)(g_controlDispCmdHandle[i].cmd)) && (g_controlDispCmdHandle[i].func != NULL)) {
253 return g_controlDispCmdHandle[i].func(client, data, reply);
254 }
255 }
256 return HDF_FAILURE;
257 }
258
ControlHostCreateAndBind(struct HdfDeviceObject * device)259 static struct ControlHost *ControlHostCreateAndBind(struct HdfDeviceObject *device)
260 {
261 struct ControlHost *controlHost = NULL;
262
263 if (device == NULL) {
264 ADM_LOG_ERR("Input params check error: device is NULL.");
265 return NULL;
266 }
267
268 controlHost = (struct ControlHost *)OsalMemCalloc(sizeof(*controlHost));
269 if (controlHost == NULL) {
270 ADM_LOG_ERR("Malloc controlHost fail!");
271 return NULL;
272 }
273 controlHost->device = device;
274 device->service = &controlHost->service;
275 return controlHost;
276 }
277
AudioControlBind(struct HdfDeviceObject * device)278 static int32_t AudioControlBind(struct HdfDeviceObject *device)
279 {
280 struct ControlHost *controlHost = NULL;
281 ADM_LOG_DEBUG("entry.");
282
283 if (device == NULL) {
284 ADM_LOG_ERR("Input params check error: device is NULL.");
285 return HDF_FAILURE;
286 }
287
288 controlHost = ControlHostCreateAndBind(device);
289 if (controlHost == NULL) {
290 ADM_LOG_ERR("controlHost is NULL.");
291 return HDF_FAILURE;
292 }
293
294 controlHost->service.Dispatch = ControlDispatch;
295
296 ADM_LOG_INFO("success.");
297 return HDF_SUCCESS;
298 }
299
AudioControlInit(struct HdfDeviceObject * device)300 static int32_t AudioControlInit(struct HdfDeviceObject *device)
301 {
302 (void)device;
303 ADM_LOG_INFO("success.");
304 return HDF_SUCCESS;
305 }
306
AudioControlRelease(struct HdfDeviceObject * device)307 static void AudioControlRelease(struct HdfDeviceObject *device)
308 {
309 struct ControlHost *controlHost = NULL;
310
311 if (device == NULL) {
312 ADM_LOG_ERR("Input params check error: device is NULL.");
313 return;
314 }
315
316 controlHost = (struct ControlHost *)device->service;
317 if (controlHost == NULL) {
318 ADM_LOG_ERR("controlHost is NULL.");
319 return;
320 }
321 OsalMemFree(controlHost);
322 }
323
324 /* HdfDriverEntry definitions */
325 struct HdfDriverEntry g_audioControlEntry = {
326 .moduleVersion = 1,
327 .moduleName = "HDF_AUDIO_CONTROL",
328 .Bind = AudioControlBind,
329 .Init = AudioControlInit,
330 .Release = AudioControlRelease,
331 };
332 HDF_INIT(g_audioControlEntry);
333