1 /*
2 * Copyright 2017-2018, NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include <assert.h>
10 #include <string.h>
11
12 #include "fsl_common.h"
13
14 #include "srtm_heap.h"
15 #include "srtm_list.h"
16 #include "srtm_dispatcher.h"
17 #include "srtm_service.h"
18 #include "srtm_service_struct.h"
19 #include "srtm_audio_service.h"
20 #include "srtm_message.h"
21 #include "srtm_message_struct.h"
22 #include "srtm_channel.h"
23 #include "srtm_channel_struct.h"
24
25 /*******************************************************************************
26 * Definitions
27 ******************************************************************************/
28 /* Protocol definition */
29 #define SRTM_AUDIO_CATEGORY (0x3U)
30
31 #define SRTM_AUDIO_VERSION (0x0102U)
32
33 #define SRTM_AUDIO_RETURN_CODE_SUCEESS (0x0U)
34 #define SRTM_AUDIO_RETURN_CODE_FAIL (0x1U)
35 #define SRTM_AUDIO_RETURN_CODE_UNSUPPORTED (0x2U)
36
37 /* Audio Service Request Command definition */
38 #define SRTM_AUDIO_CMD_TX_OPEN (0x0U)
39 #define SRTM_AUDIO_CMD_TX_START (0x1U)
40 #define SRTM_AUDIO_CMD_TX_PAUSE (0x2U)
41 #define SRTM_AUDIO_CMD_TX_RESTART (0x3U)
42 #define SRTM_AUDIO_CMD_TX_STOP (0x4U)
43 #define SRTM_AUDIO_CMD_TX_CLOSE (0x5U)
44 #define SRTM_AUDIO_CMD_TX_SET_PARAM (0x6U)
45 #define SRTM_AUDIO_CMD_TX_SET_BUF (0x7U)
46 #define SRTM_AUDIO_CMD_TX_SUSPEND (0x8U)
47 #define SRTM_AUDIO_CMD_TX_RESUME (0x9U)
48 #define SRTM_AUDIO_CMD_RX_OPEN (0xAU)
49 #define SRTM_AUDIO_CMD_RX_START (0xBU)
50 #define SRTM_AUDIO_CMD_RX_PAUSE (0xCU)
51 #define SRTM_AUDIO_CMD_RX_RESTART (0xDU)
52 #define SRTM_AUDIO_CMD_RX_STOP (0xEU)
53 #define SRTM_AUDIO_CMD_RX_CLOSE (0xFU)
54 #define SRTM_AUDIO_CMD_RX_SET_PARAM (0x10U)
55 #define SRTM_AUDIO_CMD_RX_SET_BUF (0x11U)
56 #define SRTM_AUDIO_CMD_RX_SUSPEND (0x12U)
57 #define SRTM_AUDIO_CMD_RX_RESUME (0x13U)
58 #define SRTM_AUDIO_CMD_SET_CODEC_REG (0x14U)
59 #define SRTM_AUDIO_CMD_GET_CODEC_REG (0x15U)
60 #define SRTM_AUDIO_CMD_TX_GET_BUF_OFFSET (0x16U)
61 #define SRTM_AUDIO_CMD_RX_GET_BUF_OFFSET (0x17U)
62
63 /* Audio Service Notification Command definition */
64 #define SRTM_AUDIO_NTF_TX_PERIOD_DONE (0x0U)
65 #define SRTM_AUDIO_NTF_RX_PERIOD_DONE (0x1U)
66
67 /* Audio Service Sample Format definition */
68 #define SRTM_AUDIO_SAMPLE_FORMAT_S16_LE (0x0U)
69 #define SRTM_AUDIO_SAMPLE_FORMAT_S24_LE (0x1U)
70
71 /* Audio Service Channel identifier definition */
72 #define SRTM_AUDIO_CHANNEL_LEFT (0x0U)
73 #define SRTM_AUDIO_CHANNEL_RIGHT (0x1U)
74 #define SRTM_AUDIO_CHANNEL_STEREO (0x2U)
75
76 /* Service handle */
77 typedef struct _srtm_audio_service
78 {
79 struct _srtm_service service;
80 srtm_list_t ifaces;
81 } *srtm_audio_service_t;
82
83 /* Audio interface */
84 typedef struct _srtm_audio_iface
85 {
86 srtm_list_t node;
87 uint8_t index;
88 srtm_sai_adapter_t sai;
89 srtm_codec_adapter_t codec;
90 /* Only 1 peer core is allowed to use the audio interface at any time */
91 srtm_channel_t channel;
92 srtm_list_t freeProcs;
93 uint32_t useCount;
94 } *srtm_audio_iface_t;
95
96 srtm_audio_format_map_t saiFormatMap[6] = {{SRTM_Audio_Stereo16Bits, 16U}, {SRTM_Audio_Stereo24Bits, 24U},
97 {SRTM_Audio_Stereo32Bits, 32U}, {SRTM_Audio_DSD8bits, 8U},
98 {SRTM_Audio_DSD16bits, 16U}, {SRTM_Audio_DSD32bits, 32U}};
99 static uint8_t s_audIdx;
100
101 /*******************************************************************************
102 * Prototypes
103 ******************************************************************************/
104 static srtm_audio_iface_t SRTM_AudioService_FindInterface(srtm_audio_service_t handle, uint8_t index);
105 static srtm_audio_iface_t SRTM_AudioService_FindInterfaceByChannel(srtm_audio_service_t handle, srtm_channel_t channel);
106 static srtm_audio_iface_t SRTM_AudioService_FindInterfaceByAdapter(srtm_audio_service_t handle, srtm_sai_adapter_t sai);
107
108 /*******************************************************************************
109 * Variables
110 ******************************************************************************/
111
112 /*******************************************************************************
113 * Code
114 ******************************************************************************/
SRTM_AudioService_RecycleMessage(srtm_message_t msg,void * param)115 static void SRTM_AudioService_RecycleMessage(srtm_message_t msg, void *param)
116 {
117 uint32_t primask;
118 srtm_audio_iface_t iface = (srtm_audio_iface_t)param;
119
120 /* Put message back to freeProcs */
121 primask = DisableGlobalIRQ();
122 SRTM_List_AddTail(&iface->freeProcs, &msg->node);
123 EnableGlobalIRQ(primask);
124 }
125
126 /* CALLED IN SRTM DISPATCHER TASK */
SRTM_AudioService_HandlePeriodDone(srtm_dispatcher_t dispatcher,srtm_audio_dir_t dir,srtm_audio_service_t handle,uint32_t index)127 static void SRTM_AudioService_HandlePeriodDone(srtm_dispatcher_t dispatcher,
128 srtm_audio_dir_t dir,
129 srtm_audio_service_t handle,
130 uint32_t index)
131 {
132 srtm_notification_t notif;
133 struct _srtm_audio_payload *payload;
134 uint32_t audioIdx = index >> 24U;
135 uint32_t periodIdx = index & 0xFFFFFFU;
136 srtm_audio_iface_t iface = SRTM_AudioService_FindInterface(handle, (uint8_t)audioIdx);
137
138 assert((iface != NULL) && (iface->channel != NULL));
139
140 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s: %s\r\n", __func__, dir == SRTM_AudioDirTx ? "Tx" : "Rx");
141
142 /* First allocate a notification and send to peer core */
143 notif =
144 SRTM_Notification_Create(iface->channel, SRTM_AUDIO_CATEGORY, SRTM_AUDIO_VERSION,
145 dir == SRTM_AudioDirTx ? SRTM_AUDIO_NTF_TX_PERIOD_DONE : SRTM_AUDIO_NTF_RX_PERIOD_DONE,
146 (uint16_t)sizeof(struct _srtm_audio_payload));
147 if (notif == NULL)
148 {
149 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_ERROR, "%s(%d): alloc %s notification failed.\r\n", __func__, audioIdx,
150 dir == SRTM_AudioDirTx ? "Tx" : "Rx");
151 }
152 else
153 {
154 payload = (struct _srtm_audio_payload *)(void *)SRTM_CommMessage_GetPayload(notif);
155 payload->index = (uint8_t)audioIdx;
156 payload->periodIdx = periodIdx;
157
158 (void)SRTM_Dispatcher_DeliverNotification(handle->service.dispatcher, notif);
159 }
160 }
161
SRTM_AudioService_HandleTxPeriodDone(srtm_dispatcher_t dispatcher,void * param1,void * param2)162 static void SRTM_AudioService_HandleTxPeriodDone(srtm_dispatcher_t dispatcher, void *param1, void *param2)
163 {
164 SRTM_AudioService_HandlePeriodDone(dispatcher, SRTM_AudioDirTx, (srtm_audio_service_t)param1,
165 (uint32_t)(uint8_t *)param2);
166 }
167
SRTM_AudioService_HandleRxPeriodDone(srtm_dispatcher_t dispatcher,void * param1,void * param2)168 static void SRTM_AudioService_HandleRxPeriodDone(srtm_dispatcher_t dispatcher, void *param1, void *param2)
169 {
170 SRTM_AudioService_HandlePeriodDone(dispatcher, SRTM_AudioDirRx, (srtm_audio_service_t)param1,
171 (uint32_t)(uint8_t *)param2);
172 }
173
174 /* CALLED IN AUDIO DRIVER ISR */
SRTM_AudioService_PeriodDone(srtm_service_t service,srtm_audio_dir_t dir,uint8_t index,uint32_t periodIdx)175 static srtm_status_t SRTM_AudioService_PeriodDone(srtm_service_t service,
176 srtm_audio_dir_t dir,
177 uint8_t index,
178 uint32_t periodIdx)
179 {
180 srtm_audio_service_t handle = (srtm_audio_service_t)(void *)service;
181 srtm_audio_iface_t iface = SRTM_AudioService_FindInterface(handle, index);
182 uint32_t primask;
183 srtm_list_t *list;
184 srtm_procedure_t proc = NULL;
185 srtm_status_t status;
186
187 assert(iface != NULL);
188
189 primask = DisableGlobalIRQ();
190 if (!SRTM_List_IsEmpty(&iface->freeProcs))
191 {
192 list = iface->freeProcs.next;
193 SRTM_List_Remove(list);
194 proc = SRTM_LIST_OBJ(srtm_procedure_t, node, list);
195 }
196 EnableGlobalIRQ(primask);
197
198 assert(proc != NULL); /* For debugging the shortage of procedure messages */
199
200 if (proc == NULL)
201 {
202 status = SRTM_Status_OutOfMemory;
203 }
204 else
205 {
206 proc->channel = iface->channel;
207 proc->procMsg.cb =
208 dir == SRTM_AudioDirTx ? SRTM_AudioService_HandleTxPeriodDone : SRTM_AudioService_HandleRxPeriodDone;
209 proc->procMsg.param1 = service;
210 proc->procMsg.param2 = (void *)(uint8_t *)((((uint32_t)index) << 24U) | (periodIdx & 0xFFFFFFU));
211 status = SRTM_Dispatcher_PostProc(service->dispatcher, proc);
212 }
213
214 return status;
215 }
216
SRTM_AudioService_GetRespLen(uint8_t command)217 static uint16_t SRTM_AudioService_GetRespLen(uint8_t command)
218 {
219 return (uint16_t)sizeof(struct _srtm_audio_payload);
220 }
221
222 /* Both request and notify are called from SRTM dispatcher context */
SRTM_AudioService_Request(srtm_service_t service,srtm_request_t request)223 static srtm_status_t SRTM_AudioService_Request(srtm_service_t service, srtm_request_t request)
224 {
225 srtm_status_t status;
226 srtm_audio_service_t handle = (srtm_audio_service_t)(void *)service;
227 srtm_audio_iface_t iface;
228 srtm_sai_adapter_t sai;
229 srtm_codec_adapter_t codec;
230 srtm_channel_t channel;
231 uint8_t command;
232 uint32_t payloadLen;
233 uint32_t regVal;
234 uint32_t bufOffset;
235 srtm_response_t response;
236 struct _srtm_audio_payload *audioReq;
237 uint8_t *audioRespBuf;
238 struct _srtm_audio_payload *audioResp;
239
240 assert(service->dispatcher != NULL);
241
242 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
243
244 channel = SRTM_CommMessage_GetChannel(request);
245 command = SRTM_CommMessage_GetCommand(request);
246 audioReq = (struct _srtm_audio_payload *)(void *)SRTM_CommMessage_GetPayload(request);
247 payloadLen = SRTM_CommMessage_GetPayloadLen(request);
248
249 response = SRTM_Response_Create(channel, SRTM_AUDIO_CATEGORY, SRTM_AUDIO_VERSION, command,
250 SRTM_AudioService_GetRespLen(command));
251 if (response == NULL)
252 {
253 return SRTM_Status_OutOfMemory;
254 }
255
256 audioRespBuf = (uint8_t *)SRTM_CommMessage_GetPayload(response);
257 audioResp = (struct _srtm_audio_payload *)(void *)audioRespBuf;
258
259 status = SRTM_Service_CheckVersion(service, request, SRTM_AUDIO_VERSION);
260 if ((status != SRTM_Status_Success) || (audioReq == NULL) || (payloadLen != sizeof(struct _srtm_audio_payload)))
261 {
262 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: format error!\r\n", __func__);
263 audioRespBuf[0] = (audioReq != NULL) ? audioReq->index : 0U;
264 audioRespBuf[1] = SRTM_AUDIO_RETURN_CODE_UNSUPPORTED;
265 }
266 else
267 {
268 audioRespBuf[0] = audioReq->index;
269 iface = SRTM_AudioService_FindInterfaceByChannel(handle, request->channel);
270 if (iface == NULL)
271 {
272 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: audio interface for channel 0x%x not found!\r\n", __func__,
273 request->channel);
274 audioRespBuf[1] = SRTM_AUDIO_RETURN_CODE_FAIL;
275 }
276 else
277 {
278 audioRespBuf[0] = iface->index;
279 sai = iface->sai;
280 codec = iface->codec;
281 switch (command)
282 {
283 case SRTM_AUDIO_CMD_TX_OPEN:
284 /* Only when no one else is using the audio interface, we can open it. */
285 if ((sai != NULL) && (sai->open != NULL))
286 {
287 status = sai->open(sai, SRTM_AudioDirTx, iface->index);
288 }
289 else
290 {
291 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: audio interface %d tx open unavailable!\r\n",
292 __func__, iface->index);
293 status = SRTM_Status_Error;
294 }
295 if (status == SRTM_Status_Success)
296 {
297 iface->useCount++;
298 audioRespBuf[1] = SRTM_AUDIO_RETURN_CODE_SUCEESS;
299 }
300 else
301 {
302 audioRespBuf[1] = SRTM_AUDIO_RETURN_CODE_FAIL;
303 }
304 break;
305 case SRTM_AUDIO_CMD_TX_START:
306 if ((sai != NULL) && (sai->start != NULL))
307 {
308 status = sai->start(sai, SRTM_AudioDirTx, iface->index);
309 }
310 else
311 {
312 status = SRTM_Status_Error;
313 }
314 audioRespBuf[1] =
315 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
316 break;
317 case SRTM_AUDIO_CMD_TX_PAUSE:
318 if ((sai != NULL) && (sai->pause != NULL))
319 {
320 status = sai->pause(sai, SRTM_AudioDirTx, iface->index);
321 }
322 else
323 {
324 status = SRTM_Status_Error;
325 }
326 audioRespBuf[1] =
327 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
328 break;
329 case SRTM_AUDIO_CMD_TX_RESTART:
330 if ((sai != NULL) && (sai->restart != NULL))
331 {
332 status = sai->restart(sai, SRTM_AudioDirTx, iface->index);
333 }
334 else
335 {
336 status = SRTM_Status_Error;
337 }
338 audioRespBuf[1] =
339 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
340 break;
341 case SRTM_AUDIO_CMD_TX_STOP:
342 if ((sai != NULL) && (sai->stop != NULL))
343 {
344 status = sai->stop(sai, SRTM_AudioDirTx, iface->index);
345 }
346 else
347 {
348 status = SRTM_Status_Error;
349 }
350 audioRespBuf[1] =
351 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
352 break;
353 case SRTM_AUDIO_CMD_TX_CLOSE:
354 if ((sai != NULL) && (sai->close != NULL))
355 {
356 status = sai->close(sai, SRTM_AudioDirTx, iface->index);
357 }
358 else
359 {
360 status = SRTM_Status_Error;
361 }
362 if (status == SRTM_Status_Success)
363 {
364 assert(iface->useCount > 0U);
365 iface->useCount--;
366 audioRespBuf[1] = SRTM_AUDIO_RETURN_CODE_SUCEESS;
367 }
368 else
369 {
370 audioRespBuf[1] = SRTM_AUDIO_RETURN_CODE_FAIL;
371 }
372 break;
373 case SRTM_AUDIO_CMD_TX_SET_PARAM:
374 if ((sai != NULL) && (sai->setParam != NULL))
375 {
376 status = sai->setParam(sai, SRTM_AudioDirTx, iface->index, audioReq->format, audioReq->channels,
377 audioReq->srate);
378 }
379 status = ((status == SRTM_Status_Success) && (codec != NULL) && (codec->setParam != NULL)) ?
380 codec->setParam(codec, iface->index, audioReq->format, audioReq->srate) :
381 status;
382 audioRespBuf[1] =
383 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
384 break;
385 case SRTM_AUDIO_CMD_TX_SET_BUF:
386 if ((sai != NULL) && (sai->setBuf != NULL))
387 {
388 status = sai->setBuf(sai, SRTM_AudioDirTx, iface->index, (uint8_t *)audioReq->bufAddr,
389 audioReq->bufSize, audioReq->periodSize, audioReq->periodIdx);
390 }
391 else
392 {
393 status = SRTM_Status_Error;
394 }
395 audioRespBuf[1] =
396 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
397 break;
398 case SRTM_AUDIO_CMD_TX_SUSPEND:
399 if ((sai != NULL) && (sai->suspend != NULL))
400 {
401 status = sai->suspend(sai, SRTM_AudioDirTx, iface->index);
402 }
403 else
404 {
405 status = SRTM_Status_Error;
406 }
407 audioRespBuf[1] =
408 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
409 break;
410 case SRTM_AUDIO_CMD_TX_RESUME:
411 if ((sai != NULL) && (sai->resume != NULL))
412 {
413 status = sai->resume(sai, SRTM_AudioDirTx, iface->index);
414 }
415 else
416 {
417 status = SRTM_Status_Error;
418 }
419 audioRespBuf[1] =
420 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
421 break;
422 case SRTM_AUDIO_CMD_RX_OPEN:
423 /* Only when no one else is using the audio interface, we can open it. */
424 if ((sai != NULL) && (sai->open != NULL))
425 {
426 status = sai->open(sai, SRTM_AudioDirRx, iface->index);
427 }
428 else
429 {
430 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: audio interface %d rx open unavailable!\r\n",
431 __func__, iface->index);
432 status = SRTM_Status_Error;
433 }
434 if (status == SRTM_Status_Success)
435 {
436 iface->useCount++;
437 audioRespBuf[1] = SRTM_AUDIO_RETURN_CODE_SUCEESS;
438 }
439 else
440 {
441 audioRespBuf[1] = SRTM_AUDIO_RETURN_CODE_FAIL;
442 }
443 break;
444 case SRTM_AUDIO_CMD_RX_START:
445 if ((sai != NULL) && (sai->start != NULL))
446 {
447 status = sai->start(sai, SRTM_AudioDirRx, iface->index);
448 }
449 else
450 {
451 status = SRTM_Status_Error;
452 }
453 audioRespBuf[1] =
454 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
455 break;
456 case SRTM_AUDIO_CMD_RX_PAUSE:
457 if ((sai != NULL) && (sai->pause != NULL))
458 {
459 status = sai->pause(sai, SRTM_AudioDirRx, iface->index);
460 }
461 else
462 {
463 status = SRTM_Status_Error;
464 }
465 audioRespBuf[1] =
466 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
467 break;
468 case SRTM_AUDIO_CMD_RX_RESTART:
469 if ((sai != NULL) && (sai->restart != NULL))
470 {
471 status = sai->restart(sai, SRTM_AudioDirRx, iface->index);
472 }
473 else
474 {
475 status = SRTM_Status_Error;
476 }
477 audioRespBuf[1] =
478 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
479 break;
480 case SRTM_AUDIO_CMD_RX_STOP:
481 if ((sai != NULL) && (sai->stop != NULL))
482 {
483 status = sai->stop(sai, SRTM_AudioDirRx, iface->index);
484 }
485 else
486 {
487 status = SRTM_Status_Error;
488 }
489 audioRespBuf[1] =
490 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
491 break;
492 case SRTM_AUDIO_CMD_RX_CLOSE:
493 if ((sai != NULL) && (sai->close != NULL))
494 {
495 status = sai->close(sai, SRTM_AudioDirRx, iface->index);
496 }
497 else
498 {
499 status = SRTM_Status_Error;
500 }
501 if (status == SRTM_Status_Success)
502 {
503 assert(iface->useCount > 0U);
504 iface->useCount--;
505 audioRespBuf[1] = SRTM_AUDIO_RETURN_CODE_SUCEESS;
506 }
507 else
508 {
509 audioRespBuf[1] = SRTM_AUDIO_RETURN_CODE_FAIL;
510 }
511 break;
512 case SRTM_AUDIO_CMD_RX_SET_PARAM:
513 if ((sai != NULL) && (sai->setParam != NULL))
514 {
515 status = sai->setParam(sai, SRTM_AudioDirRx, iface->index, audioReq->format, audioReq->channels,
516 audioReq->srate);
517 }
518 status = ((status == SRTM_Status_Success) && (codec != NULL) && (codec->setParam != NULL)) ?
519 codec->setParam(codec, iface->index, audioReq->format, audioReq->srate) :
520 status;
521 audioRespBuf[1] =
522 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
523 break;
524 case SRTM_AUDIO_CMD_RX_SET_BUF:
525 if ((sai != NULL) && (sai->setBuf != NULL))
526 {
527 status = sai->setBuf(sai, SRTM_AudioDirRx, iface->index, (uint8_t *)audioReq->bufAddr,
528 audioReq->bufSize, audioReq->periodSize, audioReq->periodIdx);
529 }
530 else
531 {
532 status = SRTM_Status_Error;
533 }
534 audioRespBuf[1] =
535 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
536 break;
537 case SRTM_AUDIO_CMD_RX_SUSPEND:
538 if ((sai != NULL) && (sai->suspend != NULL))
539 {
540 status = sai->suspend(sai, SRTM_AudioDirRx, iface->index);
541 }
542 else
543 {
544 status = SRTM_Status_Error;
545 }
546 audioRespBuf[1] =
547 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
548 break;
549 case SRTM_AUDIO_CMD_RX_RESUME:
550 if ((sai != NULL) && (sai->resume != NULL))
551 {
552 status = sai->resume(sai, SRTM_AudioDirRx, iface->index);
553 }
554 else
555 {
556 status = SRTM_Status_Error;
557 }
558 audioRespBuf[1] =
559 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
560 break;
561 case SRTM_AUDIO_CMD_SET_CODEC_REG:
562 if ((codec != NULL) && (codec->setReg != NULL))
563 {
564 status = codec->setReg(codec, audioReq->reg, audioReq->regVal);
565 }
566 else
567 {
568 status = SRTM_Status_Error;
569 }
570 audioRespBuf[1] =
571 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
572 break;
573 case SRTM_AUDIO_CMD_GET_CODEC_REG:
574 audioResp->reg = audioReq->reg;
575 if ((codec != NULL) && (codec->getReg != NULL))
576 {
577 status = codec->getReg(codec, audioReq->reg, ®Val);
578 audioResp->regVal = regVal;
579 }
580 else
581 {
582 status = SRTM_Status_Error;
583 }
584 audioResp->retCode =
585 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
586 break;
587 case SRTM_AUDIO_CMD_TX_GET_BUF_OFFSET:
588 if ((sai != NULL) && (sai->getBufOffset != NULL))
589 {
590 status = sai->getBufOffset(sai, SRTM_AudioDirTx, iface->index, &bufOffset);
591 audioResp->bufOffset = bufOffset;
592 }
593 else
594 {
595 status = SRTM_Status_Error;
596 }
597 audioResp->retCode =
598 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
599 break;
600 case SRTM_AUDIO_CMD_RX_GET_BUF_OFFSET:
601 if ((sai != NULL) && (sai->getBufOffset != NULL))
602 {
603 status = sai->getBufOffset(sai, SRTM_AudioDirRx, iface->index, &bufOffset);
604 audioResp->bufOffset = bufOffset;
605 }
606 else
607 {
608 status = SRTM_Status_Error;
609 }
610 audioResp->retCode =
611 status == SRTM_Status_Success ? SRTM_AUDIO_RETURN_CODE_SUCEESS : SRTM_AUDIO_RETURN_CODE_FAIL;
612 break;
613 default:
614 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: command %d unsupported!\r\n", __func__, command);
615 audioRespBuf[1] = SRTM_AUDIO_RETURN_CODE_UNSUPPORTED;
616 break;
617 }
618 }
619 }
620
621 return SRTM_Dispatcher_DeliverResponse(service->dispatcher, response);
622 }
623
SRTM_AudioService_Notify(srtm_service_t service,srtm_notification_t notif)624 static srtm_status_t SRTM_AudioService_Notify(srtm_service_t service, srtm_notification_t notif)
625 {
626 srtm_status_t status;
627 srtm_audio_service_t handle = (srtm_audio_service_t)(void *)service;
628 srtm_audio_iface_t iface;
629 srtm_sai_adapter_t sai;
630 uint8_t command;
631 struct _srtm_audio_payload *payload;
632 uint32_t payloadLen;
633
634 assert(service->dispatcher != NULL);
635
636 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
637
638 command = SRTM_CommMessage_GetCommand(notif);
639 payload = (struct _srtm_audio_payload *)(void *)SRTM_CommMessage_GetPayload(notif);
640 payloadLen = SRTM_CommMessage_GetPayloadLen(notif);
641
642 status = SRTM_Service_CheckVersion(service, notif, SRTM_AUDIO_VERSION);
643 if ((status != SRTM_Status_Success) || (payload == NULL) || (payloadLen != sizeof(struct _srtm_audio_payload)))
644 {
645 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: format error!\r\n", __func__);
646 status = SRTM_Status_ServiceNotFound;
647 }
648 else
649 {
650 iface = SRTM_AudioService_FindInterfaceByChannel(handle, notif->channel);
651 if (iface == NULL)
652 {
653 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: audio interface for channel 0x%x not found!\r\n", __func__,
654 notif->channel);
655 status = SRTM_Status_ServiceNotFound;
656 }
657 else
658 {
659 sai = iface->sai;
660 switch (command)
661 {
662 case SRTM_AUDIO_NTF_TX_PERIOD_DONE:
663 if ((sai != NULL) && (sai->periodReady != NULL))
664 {
665 status = sai->periodReady(sai, SRTM_AudioDirTx, iface->index, payload->periodIdx);
666 }
667 break;
668 case SRTM_AUDIO_NTF_RX_PERIOD_DONE:
669 if ((sai != NULL) && (sai->periodReady != NULL))
670 {
671 status = sai->periodReady(sai, SRTM_AudioDirRx, iface->index, payload->periodIdx);
672 }
673 break;
674 default:
675 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: command %d unsupported!\r\n", __func__, command);
676 break;
677 }
678 }
679 }
680
681 return status;
682 }
683
SRTM_AudioService_CreateIface(srtm_audio_service_t handle,uint8_t index,srtm_sai_adapter_t sai,srtm_codec_adapter_t codec)684 static srtm_audio_iface_t SRTM_AudioService_CreateIface(srtm_audio_service_t handle,
685 uint8_t index,
686 srtm_sai_adapter_t sai,
687 srtm_codec_adapter_t codec)
688 {
689 srtm_audio_iface_t iface = NULL;
690 srtm_procedure_t proc;
691 uint32_t i;
692
693 if ((sai != NULL) || (codec != NULL))
694 {
695 iface = (srtm_audio_iface_t)SRTM_Heap_Malloc(sizeof(struct _srtm_audio_iface));
696 assert(iface != NULL);
697
698 if (sai != NULL)
699 {
700 sai->service = &handle->service;
701 sai->periodDone = SRTM_AudioService_PeriodDone;
702 }
703 iface->index = index;
704 iface->useCount = 0;
705 iface->sai = sai;
706 iface->codec = codec;
707 iface->channel = NULL;
708 /* Create procedure messages list to be used in ISR */
709 SRTM_List_Init(&iface->freeProcs);
710 for (i = 0; i < SRTM_AUDIO_SERVICE_CONFIG_PROC_NUMBER; i++)
711 {
712 proc = SRTM_Procedure_Create(NULL, NULL, NULL);
713 assert(proc != NULL);
714 SRTM_Message_SetFreeFunc(proc, SRTM_AudioService_RecycleMessage, iface);
715 SRTM_List_AddTail(&iface->freeProcs, &proc->node);
716 }
717 }
718
719 return iface;
720 }
721
SRTM_AudioService_DestroyIface(srtm_audio_iface_t iface)722 static void SRTM_AudioService_DestroyIface(srtm_audio_iface_t iface)
723 {
724 srtm_list_t *list;
725 srtm_procedure_t proc;
726
727 assert(iface != NULL);
728
729 /* iface must be unregistered from audio service */
730 SRTM_List_Remove(&iface->node);
731
732 while (!SRTM_List_IsEmpty(&iface->freeProcs))
733 {
734 list = iface->freeProcs.next;
735 SRTM_List_Remove(list);
736 proc = SRTM_LIST_OBJ(srtm_procedure_t, node, list);
737 SRTM_Message_SetFreeFunc(proc, NULL, NULL);
738 SRTM_Message_Destroy(proc);
739 }
740
741 SRTM_Heap_Free(iface);
742 }
743
SRTM_AudioService_FindInterface(srtm_audio_service_t handle,uint8_t index)744 static srtm_audio_iface_t SRTM_AudioService_FindInterface(srtm_audio_service_t handle, uint8_t index)
745 {
746 srtm_list_t *list;
747 srtm_audio_iface_t iface = NULL;
748 srtm_audio_iface_t cur_iface = NULL;
749
750 for (list = handle->ifaces.next; list != &handle->ifaces; list = list->next)
751 {
752 cur_iface = SRTM_LIST_OBJ(srtm_audio_iface_t, node, list);
753 if (cur_iface->index == index)
754 {
755 iface = cur_iface;
756 break;
757 }
758 }
759
760 return iface;
761 }
762
SRTM_AudioService_FindInterfaceByChannel(srtm_audio_service_t handle,srtm_channel_t channel)763 static srtm_audio_iface_t SRTM_AudioService_FindInterfaceByChannel(srtm_audio_service_t handle, srtm_channel_t channel)
764 {
765 srtm_list_t *list;
766 srtm_audio_iface_t iface = NULL;
767 srtm_audio_iface_t cur_iface = NULL;
768
769 for (list = handle->ifaces.next; list != &handle->ifaces; list = list->next)
770 {
771 cur_iface = SRTM_LIST_OBJ(srtm_audio_iface_t, node, list);
772 if (cur_iface->channel == channel)
773 {
774 iface = cur_iface;
775 break;
776 }
777 }
778
779 return iface;
780 }
781
SRTM_AudioService_FindInterfaceByAdapter(srtm_audio_service_t handle,srtm_sai_adapter_t sai)782 static srtm_audio_iface_t SRTM_AudioService_FindInterfaceByAdapter(srtm_audio_service_t handle, srtm_sai_adapter_t sai)
783 {
784 srtm_list_t *list;
785 srtm_audio_iface_t iface = NULL;
786 srtm_audio_iface_t cur_iface = NULL;
787
788 for (list = handle->ifaces.next; list != &handle->ifaces; list = list->next)
789 {
790 cur_iface = SRTM_LIST_OBJ(srtm_audio_iface_t, node, list);
791 if (cur_iface->sai == sai)
792 {
793 iface = cur_iface;
794 break;
795 }
796 }
797
798 return iface;
799 }
800
SRTM_AudioService_Create(srtm_sai_adapter_t sai,srtm_codec_adapter_t codec)801 srtm_service_t SRTM_AudioService_Create(srtm_sai_adapter_t sai, srtm_codec_adapter_t codec)
802 {
803 srtm_audio_service_t handle;
804 srtm_audio_iface_t iface;
805
806 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
807
808 handle = (srtm_audio_service_t)SRTM_Heap_Malloc(sizeof(struct _srtm_audio_service));
809 assert(handle != NULL);
810
811 SRTM_List_Init(&handle->service.node);
812 handle->service.dispatcher = NULL;
813 handle->service.category = SRTM_AUDIO_CATEGORY;
814 handle->service.destroy = SRTM_AudioService_Destroy;
815 handle->service.request = SRTM_AudioService_Request;
816 handle->service.notify = SRTM_AudioService_Notify;
817
818 SRTM_List_Init(&handle->ifaces);
819 iface = SRTM_AudioService_CreateIface(handle, 0, sai, codec);
820 if (iface != NULL)
821 {
822 SRTM_List_AddTail(&handle->ifaces, &iface->node);
823 }
824
825 return &handle->service;
826 }
827
SRTM_AudioService_Destroy(srtm_service_t service)828 void SRTM_AudioService_Destroy(srtm_service_t service)
829 {
830 srtm_list_t *list;
831 srtm_audio_iface_t iface;
832 srtm_audio_service_t handle = (srtm_audio_service_t)(void *)service;
833
834 assert(service != NULL);
835
836 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
837
838 /* Service must be unregistered from dispatcher before destroy */
839 assert(SRTM_List_IsEmpty(&service->node));
840
841 while (!SRTM_List_IsEmpty(&handle->ifaces))
842 {
843 list = handle->ifaces.next;
844 SRTM_List_Remove(list);
845 iface = SRTM_LIST_OBJ(srtm_audio_iface_t, node, list);
846 SRTM_AudioService_DestroyIface(iface);
847 }
848
849 SRTM_Heap_Free(handle);
850 }
851
SRTM_AudioService_Reset(srtm_service_t service,srtm_peercore_t core)852 void SRTM_AudioService_Reset(srtm_service_t service, srtm_peercore_t core)
853 {
854 srtm_audio_service_t handle = (srtm_audio_service_t)(void *)service;
855 srtm_list_t *list;
856 srtm_audio_iface_t iface;
857
858 assert(service != NULL);
859
860 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
861
862 for (list = handle->ifaces.next; list != &handle->ifaces; list = list->next)
863 {
864 iface = SRTM_LIST_OBJ(srtm_audio_iface_t, node, list);
865 if ((iface->sai != NULL) && (iface->useCount > 0U) && (iface->channel->core == core))
866 {
867 (void)iface->sai->stop(iface->sai, SRTM_AudioDirRx, iface->index);
868 (void)iface->sai->stop(iface->sai, SRTM_AudioDirTx, iface->index);
869 (void)iface->sai->close(iface->sai, SRTM_AudioDirRx, iface->index);
870 (void)iface->sai->close(iface->sai, SRTM_AudioDirTx, iface->index);
871 }
872 iface->channel = NULL;
873 iface->useCount = 0;
874 }
875 }
876
SRTM_AudioService_BindChannel(srtm_service_t service,srtm_sai_adapter_t sai,srtm_channel_t channel)877 srtm_status_t SRTM_AudioService_BindChannel(srtm_service_t service, srtm_sai_adapter_t sai, srtm_channel_t channel)
878 {
879 srtm_status_t status = SRTM_Status_Success;
880 srtm_audio_iface_t iface;
881 srtm_audio_service_t handle = (srtm_audio_service_t)(void *)service;
882
883 assert(service != NULL);
884 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s(0x%x)\r\n", __func__, channel);
885
886 iface = SRTM_AudioService_FindInterfaceByAdapter(handle, sai);
887 if (iface != NULL)
888 {
889 iface->channel = channel;
890 }
891 else
892 {
893 status = SRTM_Status_ServiceNotFound;
894 }
895
896 return status;
897 }
898
SRTM_AudioService_AddAudioInterface(srtm_service_t service,srtm_sai_adapter_t sai)899 srtm_status_t SRTM_AudioService_AddAudioInterface(srtm_service_t service, srtm_sai_adapter_t sai)
900 {
901 srtm_status_t status = SRTM_Status_Success;
902 srtm_audio_iface_t iface;
903 srtm_audio_service_t handle = (srtm_audio_service_t)(void *)service;
904 uint8_t index = ++s_audIdx;
905
906 assert(service != NULL);
907 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s(%d)\r\n", __func__, index);
908
909 iface = SRTM_AudioService_CreateIface(handle, index, sai, NULL);
910 if (iface != NULL)
911 {
912 SRTM_List_AddTail(&handle->ifaces, &iface->node);
913 }
914 else
915 {
916 status = SRTM_Status_InvalidParameter;
917 }
918
919 return status;
920 }
921