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, &regVal);
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