source: mainline/uspace/lib/drv/generic/remote_audio_pcm.c@ 90f05b0f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 90f05b0f was 90f05b0f, checked in by Jan Vesely <jano.vesely@…>, 13 years ago

Rename audio pcm interface.

  • Property mode set to 100644
File size: 15.6 KB
RevLine 
[c09ad29e]1/*
[90f05b0f]2 * Copyright (c) 2012 Jan Vesely
[c09ad29e]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28/** @addtogroup libdrv
29 * @{
30 */
31/** @file
32 */
33
34#include <async.h>
[f8608f2]35#include <ddf/log.h>
[c09ad29e]36#include <errno.h>
37#include <str.h>
38#include <as.h>
39#include <sys/mman.h>
40
[90f05b0f]41#include "audio_pcm_iface.h"
[c09ad29e]42#include "ddf/driver.h"
43
44typedef enum {
45 IPC_M_AUDIO_PCM_GET_INFO_STR,
46 IPC_M_AUDIO_PCM_GET_BUFFER,
47 IPC_M_AUDIO_PCM_RELEASE_BUFFER,
48 IPC_M_AUDIO_PCM_START_PLAYBACK,
49 IPC_M_AUDIO_PCM_STOP_PLAYBACK,
50 IPC_M_AUDIO_PCM_START_RECORD,
51 IPC_M_AUDIO_PCM_STOP_RECORD,
52} audio_pcm_iface_funcs_t;
53
54/*
55 * CLIENT SIDE
56 */
[90f05b0f]57int audio_pcm_get_info_str(async_exch_t *exch, const char **name)
[c09ad29e]58{
59 if (!exch)
60 return EINVAL;
61 sysarg_t name_size;
62 const int ret = async_req_1_1(exch,
63 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
64 IPC_M_AUDIO_PCM_GET_INFO_STR, &name_size);
65 if (ret == EOK && name) {
66 char *name_place = calloc(1, name_size);
67 if (!name_place) {
68 /* Make the other side fail
69 * as it waits for read request */
70 async_data_read_start(exch, (void*)-1, 0);
71 return ENOMEM;
72 }
73 const int ret =
74 async_data_read_start(exch, name_place, name_size);
75 if (ret != EOK) {
76 free(name_place);
77 return ret;
78 }
79 *name = name_place;
80 }
81 return ret;
82}
[4bbfb93]83
[90f05b0f]84int audio_pcm_get_buffer(async_exch_t *exch, void **buffer, size_t *size,
[8de7ef2]85 unsigned *id, async_client_conn_t event_rec, void* arg)
[c09ad29e]86{
[00006e0]87 if (!exch || !buffer || !size || !id)
[c09ad29e]88 return EINVAL;
[00006e0]89
90 sysarg_t buffer_size = *size, buffer_id = 0;
91 const int ret = async_req_2_2(exch,
[c09ad29e]92 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE), IPC_M_AUDIO_PCM_GET_BUFFER,
[00006e0]93 (sysarg_t)buffer_size, &buffer_size, &buffer_id);
[c09ad29e]94 if (ret == EOK) {
[722912e]95 void *dst = NULL;
[8de7ef2]96 int ret = async_share_in_start_0_0(exch, buffer_size, &dst);
[c09ad29e]97 if (ret != EOK) {
98 return ret;
99 }
[8de7ef2]100 ret = async_connect_to_me(exch, 0, 0, 0, event_rec, arg);
101 if (ret != EOK) {
102 return ret;
103 }
104
[c09ad29e]105 *buffer = dst;
106 *size = buffer_size;
107 *id = buffer_id;
[00006e0]108 }
[c09ad29e]109 return ret;
110}
[4bbfb93]111
[90f05b0f]112int audio_pcm_release_buffer(async_exch_t *exch, unsigned id)
[c09ad29e]113{
114 if (!exch)
115 return EINVAL;
116 return async_req_2_0(exch, DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
117 IPC_M_AUDIO_PCM_RELEASE_BUFFER, id);
118}
[4bbfb93]119
[90f05b0f]120int audio_pcm_start_playback(async_exch_t *exch, unsigned id,
[8de7ef2]121 unsigned parts, unsigned sample_rate, uint16_t sample_size,
122 uint8_t channels, bool sign)
[c09ad29e]123{
124 if (!exch)
125 return EINVAL;
[8de7ef2]126 const sysarg_t packed =
127 (sample_size << 16) | (channels << 8) |
[6be06d0]128 ((parts & 0x7f) << 1) | (sign ? 1 : 0);
[c09ad29e]129 return async_req_4_0(exch, DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
130 IPC_M_AUDIO_PCM_START_PLAYBACK, id, sample_rate, packed);
131}
[4bbfb93]132
[90f05b0f]133int audio_pcm_stop_playback(async_exch_t *exch, unsigned id)
[c09ad29e]134{
135 if (!exch)
136 return EINVAL;
137 return async_req_2_0(exch, DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
138 IPC_M_AUDIO_PCM_STOP_PLAYBACK, id);
139}
[4bbfb93]140
[90f05b0f]141int audio_pcm_start_record(async_exch_t *exch, unsigned id,
[a3ab774]142 unsigned parts, unsigned sample_rate, uint16_t sample_size,
143 uint8_t channels, bool sign)
[c09ad29e]144{
[a3ab774]145 if (!exch)
[c09ad29e]146 return EINVAL;
[a3ab774]147 sysarg_t packed =
148 (sample_size << 16) | (channels << 8) |
149 ((parts & 0x7f) << 1) | (sign ? 1 : 0);
[c09ad29e]150 return async_req_4_0(exch, DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
151 IPC_M_AUDIO_PCM_START_RECORD, id, sample_rate, packed);
152}
[4bbfb93]153
[90f05b0f]154int audio_pcm_stop_record(async_exch_t *exch, unsigned id)
[c09ad29e]155{
156 if (!exch)
157 return EINVAL;
158 return async_req_2_0(exch, DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
159 IPC_M_AUDIO_PCM_STOP_RECORD, id);
160}
161
162/*
163 * SERVER SIDE
164 */
165static void remote_audio_pcm_get_info_str(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
166static void remote_audio_pcm_get_buffer(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
167static void remote_audio_pcm_release_buffer(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
168static void remote_audio_pcm_start_playback(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
169static void remote_audio_pcm_stop_playback(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
170static void remote_audio_pcm_start_record(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
171static void remote_audio_pcm_stop_record(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
172
173/** Remote audio pcm buffer interface operations. */
174static remote_iface_func_ptr_t remote_audio_pcm_iface_ops[] = {
175 [IPC_M_AUDIO_PCM_GET_INFO_STR] = remote_audio_pcm_get_info_str,
176 [IPC_M_AUDIO_PCM_GET_BUFFER] = remote_audio_pcm_get_buffer,
177 [IPC_M_AUDIO_PCM_RELEASE_BUFFER] = remote_audio_pcm_release_buffer,
178 [IPC_M_AUDIO_PCM_START_PLAYBACK] = remote_audio_pcm_start_playback,
179 [IPC_M_AUDIO_PCM_STOP_PLAYBACK] = remote_audio_pcm_stop_playback,
180 [IPC_M_AUDIO_PCM_START_RECORD] = remote_audio_pcm_start_record,
181 [IPC_M_AUDIO_PCM_STOP_RECORD] = remote_audio_pcm_stop_record,
182};
183
184/** Remote audio mixer interface structure. */
[90f05b0f]185remote_iface_t remote_audio_pcm_iface = {
[c09ad29e]186 .method_count = sizeof(remote_audio_pcm_iface_ops) /
187 sizeof(remote_audio_pcm_iface_ops[0]),
188 .methods = remote_audio_pcm_iface_ops
189};
[4bbfb93]190
[c09ad29e]191void remote_audio_pcm_get_info_str(ddf_fun_t *fun, void *iface,
192 ipc_callid_t callid, ipc_call_t *call)
193{
[90f05b0f]194 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]195
196 if (!pcm_iface->get_info_str) {
197 async_answer_0(callid, ENOTSUP);
198 return;
199 }
200 const char *name = NULL;
201 const int ret = pcm_iface->get_info_str(fun, &name);
202 const size_t name_size = name ? str_size(name) + 1 : 0;
203 async_answer_1(callid, ret, name_size);
204 /* Send the string. */
205 if (ret == EOK && name_size > 0) {
206 size_t size;
207 ipc_callid_t name_id;
208 if (!async_data_read_receive(&name_id, &size)) {
209 async_answer_0(name_id, EPARTY);
210 return;
211 }
212 if (size != name_size) {
213 async_answer_0(name_id, ELIMIT);
214 return;
215 }
216 async_data_read_finalize(name_id, name, name_size);
217 }
218}
[4bbfb93]219
[c09ad29e]220void remote_audio_pcm_get_buffer(ddf_fun_t *fun, void *iface,
221 ipc_callid_t callid, ipc_call_t *call)
222{
[90f05b0f]223 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]224
[8de7ef2]225 if (!pcm_iface->get_buffer ||
226 !pcm_iface->release_buffer ||
227 !pcm_iface->set_event_session) {
[c09ad29e]228 async_answer_0(callid, ENOTSUP);
229 return;
230 }
231 void *buffer = NULL;
[00006e0]232 size_t size = DEV_IPC_GET_ARG1(*call);
[c09ad29e]233 unsigned id = 0;
[8de7ef2]234 int ret = pcm_iface->get_buffer(fun, &buffer, &size, &id);
[c09ad29e]235 async_answer_2(callid, ret, size, id);
[8de7ef2]236 if (ret != EOK || size == 0)
237 return;
238
[c09ad29e]239 /* Share the buffer. */
[8de7ef2]240 size_t share_size = 0;
241 ipc_callid_t share_id = 0;
[7364c6ee]242
243 ddf_msg(LVL_DEBUG2, "Receiving share request.");
[8de7ef2]244 if (!async_share_in_receive(&share_id, &share_size)) {
245 ddf_msg(LVL_DEBUG, "Failed to share pcm buffer.");
[7364c6ee]246 pcm_iface->release_buffer(fun, id);
[8de7ef2]247 async_answer_0(share_id, EPARTY);
248 return;
249 }
[7364c6ee]250
251 ddf_msg(LVL_DEBUG2, "Checking requested share size.");
[8de7ef2]252 if (share_size != size) {
253 ddf_msg(LVL_DEBUG, "Incorrect pcm buffer size requested.");
[7364c6ee]254 pcm_iface->release_buffer(fun, id);
[8de7ef2]255 async_answer_0(share_id, ELIMIT);
256 return;
257 }
[7364c6ee]258
259 ddf_msg(LVL_DEBUG2, "Calling share finalize.");
260 ret = async_share_in_finalize(share_id, buffer, AS_AREA_WRITE
261 | AS_AREA_READ);
[8de7ef2]262 if (ret != EOK) {
[7364c6ee]263 ddf_msg(LVL_DEBUG, "Failed to share buffer.");
264 pcm_iface->release_buffer(fun, id);
[8de7ef2]265 return;
266 }
[7364c6ee]267
[8de7ef2]268 ddf_msg(LVL_DEBUG2, "Buffer shared with size %zu, creating callback.",
269 share_size);
270 {
271 ipc_call_t call;
272 ipc_callid_t callid = async_get_call(&call);
273 async_sess_t *sess =
274 async_callback_receive_start(EXCHANGE_ATOMIC, &call);
275 if (sess == NULL) {
276 ddf_msg(LVL_DEBUG, "Failed to create event callback");
277 pcm_iface->release_buffer(fun, id);
278 async_answer_0(callid, EAGAIN);
[c09ad29e]279 return;
280 }
[8de7ef2]281 ret = pcm_iface->set_event_session(fun, id, sess);
[f8608f2]282 if (ret != EOK) {
[8de7ef2]283 ddf_msg(LVL_DEBUG, "Failed to set event callback.");
284 pcm_iface->release_buffer(fun, id);
[7364c6ee]285 async_answer_0(callid, ret);
286 return;
[f8608f2]287 }
[7364c6ee]288 ddf_msg(LVL_DEBUG2, "Buffer and event session setup OK.");
289 async_answer_0(callid, EOK);
[c09ad29e]290 }
291}
[4bbfb93]292
[c09ad29e]293void remote_audio_pcm_release_buffer(ddf_fun_t *fun, void *iface,
294 ipc_callid_t callid, ipc_call_t *call)
295{
[90f05b0f]296 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]297
298 const unsigned id = DEV_IPC_GET_ARG1(*call);
299 const int ret = pcm_iface->release_buffer ?
300 pcm_iface->release_buffer(fun, id) : ENOTSUP;
301 async_answer_0(callid, ret);
302}
[4bbfb93]303
[c09ad29e]304void remote_audio_pcm_start_playback(ddf_fun_t *fun, void *iface,
305 ipc_callid_t callid, ipc_call_t *call)
306{
[90f05b0f]307 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]308
309 const unsigned id = DEV_IPC_GET_ARG1(*call);
310 const unsigned rate = DEV_IPC_GET_ARG2(*call);
311 const unsigned size = DEV_IPC_GET_ARG3(*call) >> 16;
[8de7ef2]312 const unsigned channels = (DEV_IPC_GET_ARG3(*call) >> 8) & UINT8_MAX;
313 const unsigned parts = (DEV_IPC_GET_ARG3(*call) >> 1) & 0x7f;
[c09ad29e]314 const bool sign = (bool)(DEV_IPC_GET_ARG3(*call) & 1);
315
316 const int ret = pcm_iface->start_playback
[8de7ef2]317 ? pcm_iface->start_playback(fun, id, parts, rate, size, channels, sign)
[c09ad29e]318 : ENOTSUP;
319 async_answer_0(callid, ret);
320}
[4bbfb93]321
[c09ad29e]322void remote_audio_pcm_stop_playback(ddf_fun_t *fun, void *iface,
323 ipc_callid_t callid, ipc_call_t *call)
324{
[90f05b0f]325 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]326
327 const unsigned id = DEV_IPC_GET_ARG1(*call);
328 const int ret = pcm_iface->stop_playback ?
329 pcm_iface->stop_playback(fun, id) : ENOTSUP;
330 async_answer_0(callid, ret);
331}
[4bbfb93]332
[c09ad29e]333void remote_audio_pcm_start_record(ddf_fun_t *fun, void *iface,
334 ipc_callid_t callid, ipc_call_t *call)
335{
[90f05b0f]336 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]337
338 const unsigned id = DEV_IPC_GET_ARG1(*call);
339 const unsigned rate = DEV_IPC_GET_ARG2(*call);
340 const unsigned size = DEV_IPC_GET_ARG3(*call) >> 16;
[a3ab774]341 const unsigned channels = (DEV_IPC_GET_ARG3(*call) >> 8) & UINT8_MAX;
342 const unsigned parts = (DEV_IPC_GET_ARG3(*call) >> 1) & 0x7f;
[c09ad29e]343 const bool sign = (bool)(DEV_IPC_GET_ARG3(*call) & 1);
344
345 const int ret = pcm_iface->start_record
[a3ab774]346 ? pcm_iface->start_record(fun, id, parts, rate, size, channels, sign)
[c09ad29e]347 : ENOTSUP;
348 async_answer_0(callid, ret);
349}
[4bbfb93]350
[c09ad29e]351void remote_audio_pcm_stop_record(ddf_fun_t *fun, void *iface,
352 ipc_callid_t callid, ipc_call_t *call)
353{
[90f05b0f]354 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]355
356 const unsigned id = DEV_IPC_GET_ARG1(*call);
357 const int ret = pcm_iface->stop_record ?
358 pcm_iface->stop_record(fun, id) : ENOTSUP;
359 async_answer_0(callid, ret);
360}
361
362#if 0
[4bbfb93]363
[c09ad29e]364void remote_audio_mixer_get_info(
365 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
366{
367 audio_mixer_iface_t *mixer_iface = iface;
368
369 if (!mixer_iface->get_info) {
370 async_answer_0(callid, ENOTSUP);
371 return;
372 }
373 const char *name = NULL;
374 unsigned items = 0;
375 const int ret = mixer_iface->get_info(fun, &name, &items);
376 const size_t name_size = name ? str_size(name) + 1 : 0;
377 async_answer_2(callid, ret, name_size, items);
378 /* Send the name. */
379 if (ret == EOK && name_size > 0) {
380 size_t size;
381 ipc_callid_t name_id;
382 if (!async_data_read_receive(&name_id, &size)) {
383 async_answer_0(name_id, EPARTY);
384 return;
385 }
386 if (size != name_size) {
387 async_answer_0(name_id, ELIMIT);
388 return;
389 }
390 async_data_read_finalize(name_id, name, name_size);
391 }
392}
[4bbfb93]393
[c09ad29e]394void remote_audio_mixer_get_item_info(
395 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
396{
397 audio_mixer_iface_t *mixer_iface = iface;
398
399 if (!mixer_iface->get_item_info) {
400 async_answer_0(callid, ENOTSUP);
401 return;
402 }
403
404 const unsigned item = DEV_IPC_GET_ARG1(*call);
405 const char *name = NULL;
406 unsigned channels = 0;
407 const int ret = mixer_iface->get_item_info(fun, item, &name, &channels);
408 const size_t name_size = name ? str_size(name) + 1 : 0;
409 async_answer_2(callid, ret, name_size, channels);
410 /* Send the name. */
411 if (ret == EOK && name_size > 0) {
412 size_t size;
413 ipc_callid_t name_id;
414 if (!async_data_read_receive(&name_id, &size)) {
415 async_answer_0(name_id, EPARTY);
416 return;
417 }
418 if (size != name_size) {
419 async_answer_0(name_id, ELIMIT);
420 return;
421 }
422 async_data_read_finalize(name_id, name, name_size);
423 }
424}
[4bbfb93]425
[c09ad29e]426void remote_audio_mixer_get_channel_info(
427 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
428{
429 audio_mixer_iface_t *mixer_iface = iface;
430
431 if (!mixer_iface->get_channel_info) {
432 async_answer_0(callid, ENOTSUP);
433 return;
434 }
435
436 const unsigned item = DEV_IPC_GET_ARG1(*call);
437 const unsigned channel = DEV_IPC_GET_ARG2(*call);
438 const char *name = NULL;
439 unsigned levels = 0;
440 const int ret =
441 mixer_iface->get_channel_info(fun, item, channel, &name, &levels);
442 const size_t name_size = name ? str_size(name) + 1 : 0;
443 async_answer_2(callid, ret, name_size, levels);
444 /* Send the name. */
445 if (ret == EOK && name_size > 0) {
446 size_t size;
447 ipc_callid_t name_id;
448 if (!async_data_read_receive(&name_id, &size)) {
449 async_answer_0(name_id, EPARTY);
450 return;
451 }
452 if (size != name_size) {
453 async_answer_0(name_id, ELIMIT);
454 return;
455 }
456 async_data_read_finalize(name_id, name, name_size);
457 }
458}
[4bbfb93]459
[c09ad29e]460void remote_audio_mixer_channel_mute_set(
461 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
462{
463 audio_mixer_iface_t *mixer_iface = iface;
464
465 if (!mixer_iface->channel_mute_set) {
466 async_answer_0(callid, ENOTSUP);
467 return;
468 }
469 const unsigned item = DEV_IPC_GET_ARG1(*call);
470 const unsigned channel = DEV_IPC_GET_ARG2(*call);
471 const bool mute = DEV_IPC_GET_ARG3(*call);
472 const int ret = mixer_iface->channel_mute_set(fun, item, channel, mute);
473 async_answer_0(callid, ret);
474}
[4bbfb93]475
[c09ad29e]476void remote_audio_mixer_channel_mute_get(
477 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
478{
479 audio_mixer_iface_t *mixer_iface = iface;
480
481 if (!mixer_iface->channel_mute_get) {
482 async_answer_0(callid, ENOTSUP);
483 return;
484 }
485 const unsigned item = DEV_IPC_GET_ARG1(*call);
486 const unsigned channel = DEV_IPC_GET_ARG2(*call);
487 bool mute = false;
488 const int ret =
489 mixer_iface->channel_mute_get(fun, item, channel, &mute);
490 async_answer_1(callid, ret, mute);
491}
[4bbfb93]492
[c09ad29e]493void remote_audio_mixer_channel_volume_set(
494 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
495{
496 audio_mixer_iface_t *mixer_iface = iface;
497
498 if (!mixer_iface->channel_volume_set) {
499 async_answer_0(callid, ENOTSUP);
500 return;
501 }
502 const unsigned item = DEV_IPC_GET_ARG1(*call);
503 const unsigned channel = DEV_IPC_GET_ARG2(*call);
504 const unsigned level = DEV_IPC_GET_ARG3(*call);
505 const int ret =
506 mixer_iface->channel_volume_set(fun, item, channel, level);
507 async_answer_0(callid, ret);
508}
[4bbfb93]509
[c09ad29e]510void remote_audio_mixer_channel_volume_get(
511 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
512{
513 audio_mixer_iface_t *mixer_iface = iface;
514
515 if (!mixer_iface->channel_volume_get) {
516 async_answer_0(callid, ENOTSUP);
517 return;
518 }
519 const unsigned item = DEV_IPC_GET_ARG1(*call);
520 const unsigned channel = DEV_IPC_GET_ARG2(*call);
521 unsigned current = 0, max = 0;
522 const int ret =
523 mixer_iface->channel_volume_get(fun, item, channel, &current, &max);
524 async_answer_2(callid, ret, current, max);
525}
526#endif
527
528/**
529 * @}
530 */
531
Note: See TracBrowser for help on using the repository browser.