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