source: mainline/uspace/lib/drv/generic/remote_audio_pcm.c@ 86fe9d1

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

libdrv: Add buffer position query.

Fix cap query:

Close exchange at the end.
Send query number instead of random value.

  • Property mode set to 100644
File size: 19.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>
[2cc5c835]35#include <devman.h>
[f8608f2]36#include <ddf/log.h>
[c09ad29e]37#include <errno.h>
38#include <str.h>
39#include <as.h>
40#include <sys/mman.h>
41
[90f05b0f]42#include "audio_pcm_iface.h"
[c09ad29e]43#include "ddf/driver.h"
44
45typedef enum {
46 IPC_M_AUDIO_PCM_GET_INFO_STR,
[2e01b3f]47 IPC_M_AUDIO_PCM_QUERY_CAPS,
[63c34d7]48 IPC_M_AUDIO_PCM_TEST_FORMAT,
[c09ad29e]49 IPC_M_AUDIO_PCM_GET_BUFFER,
50 IPC_M_AUDIO_PCM_RELEASE_BUFFER,
[fa91c0f]51 IPC_M_AUDIO_PCM_GET_BUFFER_POS,
[c09ad29e]52 IPC_M_AUDIO_PCM_START_PLAYBACK,
53 IPC_M_AUDIO_PCM_STOP_PLAYBACK,
[d86c9736]54 IPC_M_AUDIO_PCM_START_CAPTURE,
55 IPC_M_AUDIO_PCM_STOP_CAPTURE,
[c09ad29e]56} audio_pcm_iface_funcs_t;
57
58/*
59 * CLIENT SIDE
60 */
[2cc5c835]61audio_pcm_sess_t *audio_pcm_open(const char *name)
[c09ad29e]62{
[2cc5c835]63 devman_handle_t device_handle = 0;
64 const int ret = devman_fun_get_handle(name, &device_handle, 0);
65 if (ret != EOK)
66 return NULL;
67 return devman_device_connect(EXCHANGE_SERIALIZE, device_handle,
68 IPC_FLAG_BLOCKING);
69}
70
71audio_pcm_sess_t *audio_pcm_open_service(service_id_t id)
72{
73 return loc_service_connect(EXCHANGE_SERIALIZE, id, IPC_FLAG_BLOCKING);
74}
75
76void audio_pcm_close(audio_pcm_sess_t *sess)
77{
78 if (sess)
79 async_hangup(sess);
80}
81
82int audio_pcm_get_info_str(audio_pcm_sess_t *sess, const char **name)
83{
84 async_exch_t *exch = async_exchange_begin(sess);
[c09ad29e]85 sysarg_t name_size;
86 const int ret = async_req_1_1(exch,
87 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
88 IPC_M_AUDIO_PCM_GET_INFO_STR, &name_size);
89 if (ret == EOK && name) {
90 char *name_place = calloc(1, name_size);
91 if (!name_place) {
92 /* Make the other side fail
93 * as it waits for read request */
94 async_data_read_start(exch, (void*)-1, 0);
[2cc5c835]95 async_exchange_end(exch);
[c09ad29e]96 return ENOMEM;
97 }
98 const int ret =
99 async_data_read_start(exch, name_place, name_size);
100 if (ret != EOK) {
101 free(name_place);
[2cc5c835]102 async_exchange_end(exch);
[c09ad29e]103 return ret;
104 }
105 *name = name_place;
106 }
[2cc5c835]107 async_exchange_end(exch);
[c09ad29e]108 return ret;
109}
[4bbfb93]110
[2e01b3f]111int audio_pcm_query_cap(audio_pcm_sess_t *sess, audio_cap_t cap, unsigned *val)
112{
113 if (!val)
114 return EINVAL;
115 async_exch_t *exch = async_exchange_begin(sess);
[fa91c0f]116 sysarg_t value = 0;
[2e01b3f]117 const int ret = async_req_2_1(exch,
118 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE), IPC_M_AUDIO_PCM_QUERY_CAPS,
[fa91c0f]119 cap, &value);
[2e01b3f]120 if (ret == EOK)
121 *val = value;
[fa91c0f]122 async_exchange_end(exch);
123 return ret;
124}
125
126int audio_pcm_get_buffer_pos(audio_pcm_sess_t *sess, size_t *pos)
127{
128 if (!pos)
129 return EINVAL;
130 async_exch_t *exch = async_exchange_begin(sess);
131 sysarg_t value = 0;;
132 const int ret = async_req_1_1(exch,
133 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
134 IPC_M_AUDIO_PCM_GET_BUFFER_POS, &value);
135 if (ret == EOK)
136 *pos = value;
137 async_exchange_end(exch);
[2e01b3f]138 return ret;
139}
140
[63c34d7]141int audio_pcm_test_format(audio_pcm_sess_t *sess, unsigned *channels,
142 unsigned *rate, pcm_sample_format_t *format)
143{
144 async_exch_t *exch = async_exchange_begin(sess);
145 sysarg_t channels_arg = channels ? *channels : 0;
146 sysarg_t rate_arg = rate ? *rate : 0;
147 sysarg_t format_arg = format ? *format : 0;
148 const int ret = async_req_4_3(exch,
149 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
150 IPC_M_AUDIO_PCM_TEST_FORMAT, channels_arg, rate_arg, format_arg,
151 &channels_arg, &rate_arg, &format_arg);
152 async_exchange_end(exch);
153
154 /* All OK or something has changed. Verify that it was not one of the
155 * params we care about */
156 if ((ret == EOK || ret == ELIMIT)
157 && (!channels || *channels == channels_arg)
158 && (!rate || *rate == rate_arg)
159 && (!format || *format == format_arg))
160 return EOK;
161 if (channels)
162 *channels = channels_arg;
163 if (rate)
164 *rate = rate_arg;
165 if (format)
166 *format = format_arg;
167 return ret;
168}
169
[2cc5c835]170int audio_pcm_get_buffer(audio_pcm_sess_t *sess, void **buffer, size_t *size,
[b497018]171 async_client_conn_t event_rec, void* arg)
[c09ad29e]172{
[2cc5c835]173 if (!buffer || !size)
[c09ad29e]174 return EINVAL;
[00006e0]175
[2cc5c835]176 async_exch_t *exch = async_exchange_begin(sess);
177
[b497018]178 sysarg_t buffer_size = *size;
179 const int ret = async_req_2_1(exch,
[c09ad29e]180 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE), IPC_M_AUDIO_PCM_GET_BUFFER,
[b497018]181 (sysarg_t)buffer_size, &buffer_size);
[c09ad29e]182 if (ret == EOK) {
[722912e]183 void *dst = NULL;
[8de7ef2]184 int ret = async_share_in_start_0_0(exch, buffer_size, &dst);
[c09ad29e]185 if (ret != EOK) {
[2cc5c835]186 async_exchange_end(exch);
[c09ad29e]187 return ret;
188 }
[8de7ef2]189 ret = async_connect_to_me(exch, 0, 0, 0, event_rec, arg);
190 if (ret != EOK) {
[2cc5c835]191 async_exchange_end(exch);
[8de7ef2]192 return ret;
193 }
194
[c09ad29e]195 *buffer = dst;
196 *size = buffer_size;
[00006e0]197 }
[2cc5c835]198 async_exchange_end(exch);
[c09ad29e]199 return ret;
200}
[4bbfb93]201
[2cc5c835]202int audio_pcm_release_buffer(audio_pcm_sess_t *sess)
[c09ad29e]203{
[2cc5c835]204 async_exch_t *exch = async_exchange_begin(sess);
205 const int ret = async_req_1_0(exch,
206 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
[b497018]207 IPC_M_AUDIO_PCM_RELEASE_BUFFER);
[2cc5c835]208 async_exchange_end(exch);
209 return ret;
[c09ad29e]210}
[4bbfb93]211
[57e8b3b]212int audio_pcm_start_playback(audio_pcm_sess_t *sess, unsigned frames,
[346643c]213 unsigned channels, unsigned sample_rate, pcm_sample_format_t format)
[c09ad29e]214{
[57e8b3b]215 if (channels > UINT16_MAX)
[346643c]216 return EINVAL;
217 assert((format & UINT16_MAX) == format);
[57e8b3b]218 const sysarg_t packed = (channels << 16) | (format & UINT16_MAX);
[2cc5c835]219 async_exch_t *exch = async_exchange_begin(sess);
[57e8b3b]220 const int ret = async_req_4_0(exch,
[2cc5c835]221 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
222 IPC_M_AUDIO_PCM_START_PLAYBACK,
[57e8b3b]223 frames, sample_rate, packed);
[2cc5c835]224 async_exchange_end(exch);
225 return ret;
[c09ad29e]226}
[4bbfb93]227
[2cc5c835]228int audio_pcm_stop_playback(audio_pcm_sess_t *sess)
[c09ad29e]229{
[2cc5c835]230 async_exch_t *exch = async_exchange_begin(sess);
231 const int ret = async_req_1_0(exch,
232 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE),
[b497018]233 IPC_M_AUDIO_PCM_STOP_PLAYBACK);
[2cc5c835]234 async_exchange_end(exch);
235 return ret;
[c09ad29e]236}
[4bbfb93]237
[d86c9736]238int audio_pcm_start_capture(audio_pcm_sess_t *sess, unsigned frames,
[346643c]239 unsigned channels, unsigned sample_rate, pcm_sample_format_t format)
[c09ad29e]240{
[57e8b3b]241 if (channels > UINT16_MAX)
[346643c]242 return EINVAL;
243 assert((format & UINT16_MAX) == format);
[57e8b3b]244 const sysarg_t packed = (channels << 16) | (format & UINT16_MAX);
[2cc5c835]245 async_exch_t *exch = async_exchange_begin(sess);
[57e8b3b]246 const int ret = async_req_4_0(exch,
[d86c9736]247 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE), IPC_M_AUDIO_PCM_START_CAPTURE,
[57e8b3b]248 frames, sample_rate, packed);
[2cc5c835]249 async_exchange_end(exch);
250 return ret;
[c09ad29e]251}
[4bbfb93]252
[d86c9736]253int audio_pcm_stop_capture(audio_pcm_sess_t *sess)
[c09ad29e]254{
[2cc5c835]255 async_exch_t *exch = async_exchange_begin(sess);
256 const int ret = async_req_1_0(exch,
[d86c9736]257 DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE), IPC_M_AUDIO_PCM_STOP_CAPTURE);
[2cc5c835]258 async_exchange_end(exch);
259 return ret;
[c09ad29e]260}
261
262/*
263 * SERVER SIDE
264 */
265static void remote_audio_pcm_get_info_str(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[2e01b3f]266static void remote_audio_pcm_query_caps(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[fa91c0f]267static void remote_audio_pcm_get_buffer_pos(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[63c34d7]268static void remote_audio_pcm_test_format(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[c09ad29e]269static void remote_audio_pcm_get_buffer(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
270static void remote_audio_pcm_release_buffer(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
271static void remote_audio_pcm_start_playback(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
272static void remote_audio_pcm_stop_playback(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[d86c9736]273static void remote_audio_pcm_start_capture(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
274static void remote_audio_pcm_stop_capture(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
[c09ad29e]275
276/** Remote audio pcm buffer interface operations. */
277static remote_iface_func_ptr_t remote_audio_pcm_iface_ops[] = {
278 [IPC_M_AUDIO_PCM_GET_INFO_STR] = remote_audio_pcm_get_info_str,
[2e01b3f]279 [IPC_M_AUDIO_PCM_QUERY_CAPS] = remote_audio_pcm_query_caps,
[fa91c0f]280 [IPC_M_AUDIO_PCM_GET_BUFFER_POS] = remote_audio_pcm_get_buffer_pos,
[63c34d7]281 [IPC_M_AUDIO_PCM_TEST_FORMAT] = remote_audio_pcm_test_format,
[c09ad29e]282 [IPC_M_AUDIO_PCM_GET_BUFFER] = remote_audio_pcm_get_buffer,
283 [IPC_M_AUDIO_PCM_RELEASE_BUFFER] = remote_audio_pcm_release_buffer,
284 [IPC_M_AUDIO_PCM_START_PLAYBACK] = remote_audio_pcm_start_playback,
285 [IPC_M_AUDIO_PCM_STOP_PLAYBACK] = remote_audio_pcm_stop_playback,
[d86c9736]286 [IPC_M_AUDIO_PCM_START_CAPTURE] = remote_audio_pcm_start_capture,
287 [IPC_M_AUDIO_PCM_STOP_CAPTURE] = remote_audio_pcm_stop_capture,
[c09ad29e]288};
289
290/** Remote audio mixer interface structure. */
[90f05b0f]291remote_iface_t remote_audio_pcm_iface = {
[c09ad29e]292 .method_count = sizeof(remote_audio_pcm_iface_ops) /
293 sizeof(remote_audio_pcm_iface_ops[0]),
294 .methods = remote_audio_pcm_iface_ops
295};
[4bbfb93]296
[c09ad29e]297void remote_audio_pcm_get_info_str(ddf_fun_t *fun, void *iface,
298 ipc_callid_t callid, ipc_call_t *call)
299{
[90f05b0f]300 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]301
302 if (!pcm_iface->get_info_str) {
303 async_answer_0(callid, ENOTSUP);
304 return;
305 }
306 const char *name = NULL;
307 const int ret = pcm_iface->get_info_str(fun, &name);
308 const size_t name_size = name ? str_size(name) + 1 : 0;
309 async_answer_1(callid, ret, name_size);
310 /* Send the string. */
311 if (ret == EOK && name_size > 0) {
312 size_t size;
313 ipc_callid_t name_id;
314 if (!async_data_read_receive(&name_id, &size)) {
315 async_answer_0(name_id, EPARTY);
316 return;
317 }
318 if (size != name_size) {
319 async_answer_0(name_id, ELIMIT);
320 return;
321 }
322 async_data_read_finalize(name_id, name, name_size);
323 }
324}
[4bbfb93]325
[2e01b3f]326void remote_audio_pcm_query_caps(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
327{
328 const audio_pcm_iface_t *pcm_iface = iface;
329 const audio_cap_t cap = DEV_IPC_GET_ARG1(*call);
330 if (pcm_iface->query_cap) {
331 const unsigned value = pcm_iface->query_cap(fun, cap);
332 async_answer_1(callid, EOK, value);
333 } else {
334 async_answer_0(callid, ENOTSUP);
335 }
336}
[fa91c0f]337void remote_audio_pcm_get_buffer_pos(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
338{
339 const audio_pcm_iface_t *pcm_iface = iface;
340 size_t pos = 0;
341 const int ret = pcm_iface->get_buffer_pos ?
342 pcm_iface->get_buffer_pos(fun, &pos) : ENOTSUP;
343 async_answer_1(callid, ret, pos);
344}
[2e01b3f]345
346void remote_audio_pcm_test_format(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
[63c34d7]347{
348 const audio_pcm_iface_t *pcm_iface = iface;
349 unsigned channels = DEV_IPC_GET_ARG1(*call);
350 unsigned rate = DEV_IPC_GET_ARG2(*call);
351 pcm_sample_format_t format = DEV_IPC_GET_ARG3(*call);
352 const int ret = pcm_iface->test_format ?
353 pcm_iface->test_format(fun, &channels, &rate, &format) : ENOTSUP;
354 async_answer_3(callid, ret, channels, rate, format);
355}
356
[c09ad29e]357void remote_audio_pcm_get_buffer(ddf_fun_t *fun, void *iface,
358 ipc_callid_t callid, ipc_call_t *call)
359{
[90f05b0f]360 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]361
[8de7ef2]362 if (!pcm_iface->get_buffer ||
363 !pcm_iface->release_buffer ||
364 !pcm_iface->set_event_session) {
[c09ad29e]365 async_answer_0(callid, ENOTSUP);
366 return;
367 }
368 void *buffer = NULL;
[00006e0]369 size_t size = DEV_IPC_GET_ARG1(*call);
[b497018]370 int ret = pcm_iface->get_buffer(fun, &buffer, &size);
371 async_answer_1(callid, ret, size);
[8de7ef2]372 if (ret != EOK || size == 0)
373 return;
374
[c09ad29e]375 /* Share the buffer. */
[8de7ef2]376 size_t share_size = 0;
377 ipc_callid_t share_id = 0;
[7364c6ee]378
379 ddf_msg(LVL_DEBUG2, "Receiving share request.");
[8de7ef2]380 if (!async_share_in_receive(&share_id, &share_size)) {
381 ddf_msg(LVL_DEBUG, "Failed to share pcm buffer.");
[b497018]382 pcm_iface->release_buffer(fun);
[8de7ef2]383 async_answer_0(share_id, EPARTY);
384 return;
385 }
[7364c6ee]386
387 ddf_msg(LVL_DEBUG2, "Checking requested share size.");
[8de7ef2]388 if (share_size != size) {
389 ddf_msg(LVL_DEBUG, "Incorrect pcm buffer size requested.");
[b497018]390 pcm_iface->release_buffer(fun);
[8de7ef2]391 async_answer_0(share_id, ELIMIT);
392 return;
393 }
[7364c6ee]394
395 ddf_msg(LVL_DEBUG2, "Calling share finalize.");
396 ret = async_share_in_finalize(share_id, buffer, AS_AREA_WRITE
397 | AS_AREA_READ);
[8de7ef2]398 if (ret != EOK) {
[7364c6ee]399 ddf_msg(LVL_DEBUG, "Failed to share buffer.");
[b497018]400 pcm_iface->release_buffer(fun);
[8de7ef2]401 return;
402 }
[7364c6ee]403
[8de7ef2]404 ddf_msg(LVL_DEBUG2, "Buffer shared with size %zu, creating callback.",
405 share_size);
406 {
407 ipc_call_t call;
408 ipc_callid_t callid = async_get_call(&call);
409 async_sess_t *sess =
410 async_callback_receive_start(EXCHANGE_ATOMIC, &call);
411 if (sess == NULL) {
412 ddf_msg(LVL_DEBUG, "Failed to create event callback");
[b497018]413 pcm_iface->release_buffer(fun);
[8de7ef2]414 async_answer_0(callid, EAGAIN);
[c09ad29e]415 return;
416 }
[b497018]417 ret = pcm_iface->set_event_session(fun, sess);
[f8608f2]418 if (ret != EOK) {
[8de7ef2]419 ddf_msg(LVL_DEBUG, "Failed to set event callback.");
[b497018]420 pcm_iface->release_buffer(fun);
[7364c6ee]421 async_answer_0(callid, ret);
422 return;
[f8608f2]423 }
[7364c6ee]424 ddf_msg(LVL_DEBUG2, "Buffer and event session setup OK.");
425 async_answer_0(callid, EOK);
[c09ad29e]426 }
427}
[4bbfb93]428
[c09ad29e]429void remote_audio_pcm_release_buffer(ddf_fun_t *fun, void *iface,
430 ipc_callid_t callid, ipc_call_t *call)
431{
[90f05b0f]432 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]433
434 const int ret = pcm_iface->release_buffer ?
[b497018]435 pcm_iface->release_buffer(fun) : ENOTSUP;
[c09ad29e]436 async_answer_0(callid, ret);
437}
[4bbfb93]438
[c09ad29e]439void remote_audio_pcm_start_playback(ddf_fun_t *fun, void *iface,
440 ipc_callid_t callid, ipc_call_t *call)
441{
[90f05b0f]442 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]443
[57e8b3b]444 const unsigned frames = DEV_IPC_GET_ARG1(*call);
445 const unsigned rate = DEV_IPC_GET_ARG2(*call);
446 const unsigned channels = (DEV_IPC_GET_ARG3(*call) >> 16) & UINT8_MAX;
447 const pcm_sample_format_t format = DEV_IPC_GET_ARG3(*call) & UINT16_MAX;
[c09ad29e]448
449 const int ret = pcm_iface->start_playback
[57e8b3b]450 ? pcm_iface->start_playback(fun, frames, channels, rate, format)
[c09ad29e]451 : ENOTSUP;
452 async_answer_0(callid, ret);
453}
[4bbfb93]454
[c09ad29e]455void remote_audio_pcm_stop_playback(ddf_fun_t *fun, void *iface,
456 ipc_callid_t callid, ipc_call_t *call)
457{
[90f05b0f]458 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]459
460 const int ret = pcm_iface->stop_playback ?
[b497018]461 pcm_iface->stop_playback(fun) : ENOTSUP;
[c09ad29e]462 async_answer_0(callid, ret);
463}
[4bbfb93]464
[d86c9736]465void remote_audio_pcm_start_capture(ddf_fun_t *fun, void *iface,
[c09ad29e]466 ipc_callid_t callid, ipc_call_t *call)
467{
[90f05b0f]468 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]469
[57e8b3b]470 const unsigned frames = DEV_IPC_GET_ARG1(*call);
471 const unsigned rate = DEV_IPC_GET_ARG2(*call);
472 const unsigned channels = (DEV_IPC_GET_ARG3(*call) >> 16) & UINT16_MAX;
473 const pcm_sample_format_t format = DEV_IPC_GET_ARG3(*call) & UINT16_MAX;
[c09ad29e]474
[d86c9736]475 const int ret = pcm_iface->start_capture
476 ? pcm_iface->start_capture(fun, frames, channels, rate, format)
[c09ad29e]477 : ENOTSUP;
478 async_answer_0(callid, ret);
479}
[4bbfb93]480
[d86c9736]481void remote_audio_pcm_stop_capture(ddf_fun_t *fun, void *iface,
[c09ad29e]482 ipc_callid_t callid, ipc_call_t *call)
483{
[90f05b0f]484 const audio_pcm_iface_t *pcm_iface = iface;
[c09ad29e]485
[d86c9736]486 const int ret = pcm_iface->stop_capture ?
487 pcm_iface->stop_capture(fun) : ENOTSUP;
[c09ad29e]488 async_answer_0(callid, ret);
489}
490
491#if 0
[4bbfb93]492
[c09ad29e]493void remote_audio_mixer_get_info(
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->get_info) {
499 async_answer_0(callid, ENOTSUP);
500 return;
501 }
502 const char *name = NULL;
503 unsigned items = 0;
504 const int ret = mixer_iface->get_info(fun, &name, &items);
505 const size_t name_size = name ? str_size(name) + 1 : 0;
506 async_answer_2(callid, ret, name_size, items);
507 /* Send the name. */
508 if (ret == EOK && name_size > 0) {
509 size_t size;
510 ipc_callid_t name_id;
511 if (!async_data_read_receive(&name_id, &size)) {
512 async_answer_0(name_id, EPARTY);
513 return;
514 }
515 if (size != name_size) {
516 async_answer_0(name_id, ELIMIT);
517 return;
518 }
519 async_data_read_finalize(name_id, name, name_size);
520 }
521}
[4bbfb93]522
[c09ad29e]523void remote_audio_mixer_get_item_info(
524 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
525{
526 audio_mixer_iface_t *mixer_iface = iface;
527
528 if (!mixer_iface->get_item_info) {
529 async_answer_0(callid, ENOTSUP);
530 return;
531 }
532
533 const unsigned item = DEV_IPC_GET_ARG1(*call);
534 const char *name = NULL;
535 unsigned channels = 0;
536 const int ret = mixer_iface->get_item_info(fun, item, &name, &channels);
537 const size_t name_size = name ? str_size(name) + 1 : 0;
538 async_answer_2(callid, ret, name_size, channels);
539 /* Send the name. */
540 if (ret == EOK && name_size > 0) {
541 size_t size;
542 ipc_callid_t name_id;
543 if (!async_data_read_receive(&name_id, &size)) {
544 async_answer_0(name_id, EPARTY);
545 return;
546 }
547 if (size != name_size) {
548 async_answer_0(name_id, ELIMIT);
549 return;
550 }
551 async_data_read_finalize(name_id, name, name_size);
552 }
553}
[4bbfb93]554
[c09ad29e]555void remote_audio_mixer_get_channel_info(
556 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
557{
558 audio_mixer_iface_t *mixer_iface = iface;
559
560 if (!mixer_iface->get_channel_info) {
561 async_answer_0(callid, ENOTSUP);
562 return;
563 }
564
565 const unsigned item = DEV_IPC_GET_ARG1(*call);
566 const unsigned channel = DEV_IPC_GET_ARG2(*call);
567 const char *name = NULL;
568 unsigned levels = 0;
569 const int ret =
570 mixer_iface->get_channel_info(fun, item, channel, &name, &levels);
571 const size_t name_size = name ? str_size(name) + 1 : 0;
572 async_answer_2(callid, ret, name_size, levels);
573 /* Send the name. */
574 if (ret == EOK && name_size > 0) {
575 size_t size;
576 ipc_callid_t name_id;
577 if (!async_data_read_receive(&name_id, &size)) {
578 async_answer_0(name_id, EPARTY);
579 return;
580 }
581 if (size != name_size) {
582 async_answer_0(name_id, ELIMIT);
583 return;
584 }
585 async_data_read_finalize(name_id, name, name_size);
586 }
587}
[4bbfb93]588
[c09ad29e]589void remote_audio_mixer_channel_mute_set(
590 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
591{
592 audio_mixer_iface_t *mixer_iface = iface;
593
594 if (!mixer_iface->channel_mute_set) {
595 async_answer_0(callid, ENOTSUP);
596 return;
597 }
598 const unsigned item = DEV_IPC_GET_ARG1(*call);
599 const unsigned channel = DEV_IPC_GET_ARG2(*call);
600 const bool mute = DEV_IPC_GET_ARG3(*call);
601 const int ret = mixer_iface->channel_mute_set(fun, item, channel, mute);
602 async_answer_0(callid, ret);
603}
[4bbfb93]604
[c09ad29e]605void remote_audio_mixer_channel_mute_get(
606 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
607{
608 audio_mixer_iface_t *mixer_iface = iface;
609
610 if (!mixer_iface->channel_mute_get) {
611 async_answer_0(callid, ENOTSUP);
612 return;
613 }
614 const unsigned item = DEV_IPC_GET_ARG1(*call);
615 const unsigned channel = DEV_IPC_GET_ARG2(*call);
616 bool mute = false;
617 const int ret =
618 mixer_iface->channel_mute_get(fun, item, channel, &mute);
619 async_answer_1(callid, ret, mute);
620}
[4bbfb93]621
[c09ad29e]622void remote_audio_mixer_channel_volume_set(
623 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
624{
625 audio_mixer_iface_t *mixer_iface = iface;
626
627 if (!mixer_iface->channel_volume_set) {
628 async_answer_0(callid, ENOTSUP);
629 return;
630 }
631 const unsigned item = DEV_IPC_GET_ARG1(*call);
632 const unsigned channel = DEV_IPC_GET_ARG2(*call);
633 const unsigned level = DEV_IPC_GET_ARG3(*call);
634 const int ret =
635 mixer_iface->channel_volume_set(fun, item, channel, level);
636 async_answer_0(callid, ret);
637}
[4bbfb93]638
[c09ad29e]639void remote_audio_mixer_channel_volume_get(
640 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
641{
642 audio_mixer_iface_t *mixer_iface = iface;
643
644 if (!mixer_iface->channel_volume_get) {
645 async_answer_0(callid, ENOTSUP);
646 return;
647 }
648 const unsigned item = DEV_IPC_GET_ARG1(*call);
649 const unsigned channel = DEV_IPC_GET_ARG2(*call);
650 unsigned current = 0, max = 0;
651 const int ret =
652 mixer_iface->channel_volume_get(fun, item, channel, &current, &max);
653 async_answer_2(callid, ret, current, max);
654}
655#endif
656
657/**
658 * @}
659 */
660
Note: See TracBrowser for help on using the repository browser.