2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2011 George Boutsioukis for Xen
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
35 #include <sys/ioctl.h>
39 #include <pulse/xmalloc.h>
41 #include <pulsecore/core-error.h>
42 #include <pulsecore/sink.h>
43 #include <pulsecore/module.h>
44 #include <pulsecore/core-util.h>
45 #include <pulsecore/modargs.h>
46 #include <pulsecore/log.h>
47 #include <pulsecore/thread.h>
48 #include <pulsecore/thread-mq.h>
49 #include <pulsecore/rtpoll.h>
51 #include <sys/select.h>
56 #include "module-xenpv-sink-symdef.h"
60 PA_MODULE_AUTHOR("Giorgos Boutsioukis");
61 PA_MODULE_DESCRIPTION("Xen PV audio sink");
62 PA_MODULE_VERSION(PACKAGE_VERSION
);
63 PA_MODULE_LOAD_ONCE(FALSE
);
65 "sink_name=<name for the sink> "
66 "sink_properties=<properties for the sink> "
67 "format=<sample format> "
69 "channels=<number of channels> "
70 "channel_map=<channel map>");
72 #define DEFAULT_SINK_NAME "xenpv_output"
73 #define DEFAULT_FILE_NAME "xenpv_output"
75 #define STATE_UNDEFINED 9999
79 XenbusStateUnknown
= 0,
80 XenbusStateInitialising
= 1,
81 XenbusStateInitWait
= 2,
82 XenbusStateInitialised
= 3,
83 XenbusStateConnected
= 4,
84 XenbusStateClosing
= 5,
85 XenbusStateClosed
= 6,
86 XenbusStateReconfiguring
= 7,
87 XenbusStateReconfigured
= 8
90 static const char* xenbus_names
[] = {
92 "XenbusStateInitialising",
93 "XenbusStateInitWait",
94 "XenbusStateInitialised",
95 "XenbusStateConnected",
98 "XenbusStateReconfiguring",
99 "XenbusStateReconfigured"
108 pa_thread_mq thread_mq
;
111 pa_memchunk memchunk
;
113 pa_rtpoll_item
*rtpoll_item
;
121 /* just to test non- frame-aligned size */
125 uint32_t cons_indx
, prod_indx
;
126 uint32_t usable_buffer_space
; /* kept here for convenience */
127 uint8_t buffer
[BUFSIZE
];
130 static const char* const valid_modargs
[] = {
144 evtchn_port_or_error_t xen_evtchn_port
;
145 static struct xs_handle
*xsh
;
146 struct ioctl_gntalloc_alloc_gref gref
;
148 static int register_backend_state_watch(void);
149 static int wait_for_backend_state_change(void);
150 static int alloc_gref(struct ioctl_gntalloc_alloc_gref
*gref
, void **addr
);
151 static int ring_write(struct ring
*r
, void *src
, int length
);
152 static int publish_spec(pa_sample_spec
*ss
);
153 static int read_backend_default_spec(pa_sample_spec
*ss
);
154 static int publish_param(const char *paramname
, const char *value
);
155 static int publish_param_int(const char *paramname
, const int value
);
156 static char* read_param(const char *paramname
);
158 static int set_state(int state
) {
159 static int current_state
= 0;
160 pa_log_debug("State transition %s->%s\n",
161 xenbus_names
[current_state
], xenbus_names
[state
]);
163 publish_param_int("state", state
);
164 current_state
= state
;
167 #define NEGOTIATION_ERROR 2
168 #define NEGOTIATION_OK 1
170 /* negotiation callbacks */
171 static int state_unknown_cb() {
172 pa_log_debug("Xen audio sink: Backend state was XenbusStateUnknown\n");
173 set_state(XenbusStateInitialising
);
178 static int state_initialising_cb() {
179 pa_log_debug("Xen audio sink: Backend state was XenbusStateInitialising\n");
180 set_state(XenbusStateInitialised
);
184 static int state_initwait_cb() {
185 pa_log_debug("Xen audio sink: Backend state was XenbusStateInitWait\n");
189 static int state_initialised_cb() {
190 pa_log_debug("Xen audio sink: Backend state was XenbusStateInitialised\n");
191 /*Remind the backend we are ready*/
192 set_state(XenbusStateInitialised
);
196 static int state_connected_cb() {
197 /* The backend accepted our parameters, sweet! */
198 set_state(XenbusStateConnected
);
199 pa_log_debug("Xen audio sink: Backend state was XenbusStateConnected\n");
200 return NEGOTIATION_OK
;
203 static int state_closing_cb() {
204 pa_log_debug("Xen audio sink: Backend state was XenbusStateClosing\n");
208 static int state_closed_cb() {
209 pa_log_debug("Xen audio sink: Backend state was XenbusStateClosed\n");
213 static int state_reconfiguring_cb() {
214 /* The backend rejected our sample spec */
215 pa_log_debug("Xen audio sink: Backend state was XenbusStateReconfiguring\n");
216 /* fall back to the backend's default parameters*/
217 read_backend_default_spec(&ss
);
218 /* backend should accept these now */
220 set_state(XenbusStateInitialised
);
224 static int state_reconfigured_cb() {
225 pa_log_debug("Xen audio sink: Backend state was XenbusStateReconfigured\n");
229 int (*state_callbacks
[9])(void) = {
231 state_initialising_cb
,
233 state_initialised_cb
,
237 state_reconfiguring_cb
,
238 state_reconfigured_cb
241 static void xen_cleanup() {
244 munmap((void*)gref
.index
, 4096);
246 set_state(XenbusStateClosing
);
247 /* send one last event to unblock the backend */
248 xc_evtchn_notify(xce
, xen_evtchn_port
);
249 /* close xen interfaces */
250 xc_evtchn_close(xce
);
251 xc_interface_close(xch
);
253 /* delete xenstore keys */
254 publish_param_int("state", XenbusStateClosed
);
255 snprintf(keybuf
, sizeof(keybuf
), "device/audio/%d", device_id
);
256 xs_rm(xsh
, 0, keybuf
);
257 xs_daemon_close(xsh
);
260 static int sink_process_msg(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
261 struct userdata
*u
= PA_SINK(o
)->userdata
;
265 case PA_SINK_MESSAGE_GET_LATENCY
: {
268 n
+= u
->memchunk
.length
;
270 *((pa_usec_t
*) data
) = pa_bytes_to_usec(n
, &u
->sink
->sample_spec
);
275 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
278 static int process_render(struct userdata
*u
) {
282 if (u
->memchunk
.length
<= 0)
283 pa_sink_render(u
->sink
, ioring
->usable_buffer_space
, &u
->memchunk
);
286 pa_assert(u
->memchunk
.length
> 0);
288 xc_evtchn_notify(xce
, xen_evtchn_port
);
293 p
= pa_memblock_acquire(u
->memchunk
.memblock
);
294 /* xen: write data to ring buffer & notify backend */
295 l
= ring_write(ioring
, (uint8_t*)p
+ u
->memchunk
.index
, u
->memchunk
.length
);
297 pa_memblock_release(u
->memchunk
.memblock
);
304 else if (errno
== EAGAIN
)
307 pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno
));
313 u
->memchunk
.index
+= (size_t) l
;
314 u
->memchunk
.length
-= (size_t) l
;
316 if (u
->memchunk
.length
<= 0) {
317 pa_memblock_unref(u
->memchunk
.memblock
);
318 pa_memchunk_reset(&u
->memchunk
);
326 static void thread_func(void *userdata
) {
327 struct userdata
*u
= userdata
;
331 pa_log_debug("Thread starting up");
333 pa_thread_mq_install(&u
->thread_mq
);
336 struct pollfd
*pollfd
;
339 pollfd
= pa_rtpoll_item_get_pollfd(u
->rtpoll_item
, NULL
);
341 /* Render some data and write it to the fifo */
342 if (PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
)) {
344 if (u
->sink
->thread_info
.rewind_requested
)
345 pa_sink_process_rewind(u
->sink
, 0);
347 if (pollfd
->revents
) {
348 if (process_render(u
) < 0)
355 /* Hmm, nothing to do. Let's sleep */
357 pollfd
->events
= (short) (u
->sink
->thread_info
.state
== PA_SINK_RUNNING
? POLLOUT
: 0);
359 if ((ret
= pa_rtpoll_run(u
->rtpoll
, TRUE
)) < 0)
365 pollfd
= pa_rtpoll_item_get_pollfd(u
->rtpoll_item
, NULL
);
367 if (pollfd
->revents
& ~POLLOUT
) {
368 pa_log("FIFO shutdown.");
374 /* If this was no regular exit from the loop we have to continue
375 * processing messages until we received PA_MESSAGE_SHUTDOWN */
376 pa_asyncmsgq_post(u
->thread_mq
.outq
, PA_MSGOBJECT(u
->core
), PA_CORE_MESSAGE_UNLOAD_MODULE
, u
->module
, 0, NULL
, NULL
);
377 pa_asyncmsgq_wait_for(u
->thread_mq
.inq
, PA_MESSAGE_SHUTDOWN
);
378 pa_log_debug("Shutting down Xen...");
381 pa_log_debug("Thread shutting down");
384 int pa__init(pa_module
*m
) {
388 pa_sink_new_data data
;
395 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
396 pa_log("Failed to parse module arguments.");
400 ss
= m
->core
->default_sample_spec
;
401 map
= m
->core
->default_channel_map
;
403 /* user arguments override these */
404 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
405 pa_log("Invalid sample format specification or channel map");
410 xsh
= xs_domain_open();
412 pa_log("xs_domain_open failed");
415 set_state(XenbusStateUnknown
);
417 xch
= xc_interface_open(NULL
, NULL
, 0);
419 pa_log("xc_interface_open failed");
423 xce
= xc_evtchn_open(NULL
, 0);
425 pa_log("xc_evtchn_open failed");
429 /* use only dom0 as the backend for now */
430 xen_evtchn_port
= xc_evtchn_bind_unbound_port(xce
, 0);
431 if (xen_evtchn_port
== 0) {
432 pa_log("xc_evtchn_bind_unbound_port failed");
435 /* get grant reference & map locally */
436 if (alloc_gref(&gref
, (void**)&ioring
)) {
437 pa_log("alloc_gref failed");
439 device_id
= 0; /* hardcoded for now */
441 if (register_backend_state_watch()) {
442 pa_log("Xen sink: register xenstore watch failed");
445 publish_param_int("event-channel", xen_evtchn_port
);
446 publish_param_int("ring-ref", gref
.gref_ids
[0]);
448 /* let's ask for something absurd and deal with rejection */
455 backend_state
= wait_for_backend_state_change();
456 if (backend_state
== STATE_UNDEFINED
) {
457 pa_log("Xen Backend is taking long to respond, still waiting...");
459 } else if (backend_state
== -1) {
460 pa_log("Error while waiting for backend: %s", strerror(errno
));
464 ret
= state_callbacks
[backend_state
]();
466 if (ret
!=NEGOTIATION_OK
) {
467 pa_log("Negotiation with Xen backend failed!");
471 pa_sample_spec_snprint(strbuf
, 100, &ss
);
472 pa_log_debug("Negotiation ended, the result was: %s", strbuf
);
474 /* End of Phase 2, begin playback cycle */
476 u
= pa_xnew0(struct userdata
, 1);
480 pa_memchunk_reset(&u
->memchunk
);
481 u
->rtpoll
= pa_rtpoll_new();
482 pa_thread_mq_init(&u
->thread_mq
, m
->core
->mainloop
, u
->rtpoll
);
485 /* init ring buffer */
486 ioring
->prod_indx
= ioring
->cons_indx
= 0;
487 ioring
->usable_buffer_space
= BUFSIZE
- BUFSIZE
% pa_frame_size(&ss
);
489 pa_sink_new_data_init(&data
);
490 data
.driver
= __FILE__
;
492 pa_sink_new_data_set_name(&data
, pa_modargs_get_value(ma
, "sink_name", DEFAULT_SINK_NAME
));
493 pa_proplist_sets(data
.proplist
, PA_PROP_DEVICE_STRING
, "xensink");
494 pa_proplist_setf(data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "Xen PV audio sink");
495 pa_sink_new_data_set_sample_spec(&data
, &ss
);
496 pa_sink_new_data_set_channel_map(&data
, &map
);
498 if (pa_modargs_get_proplist(ma
, "sink_properties", data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
499 pa_log("Invalid properties");
500 pa_sink_new_data_done(&data
);
504 u
->sink
= pa_sink_new(m
->core
, &data
, PA_SINK_LATENCY
);
505 pa_sink_new_data_done(&data
);
508 pa_log("Failed to create sink.");
512 u
->sink
->parent
.process_msg
= sink_process_msg
;
513 u
->sink
->userdata
= u
;
515 pa_sink_set_asyncmsgq(u
->sink
, u
->thread_mq
.inq
);
516 pa_sink_set_rtpoll(u
->sink
, u
->rtpoll
);
517 pa_sink_set_max_request(u
->sink
, ioring
->usable_buffer_space
);
518 pa_sink_set_fixed_latency(u
->sink
, pa_bytes_to_usec(ioring
->usable_buffer_space
, &u
->sink
->sample_spec
));
520 u
->rtpoll_item
= pa_rtpoll_item_new(u
->rtpoll
, PA_RTPOLL_NEVER
, 1);
522 if (!(u
->thread
= pa_thread_new("xenpv-sink", thread_func
, u
))) {
523 pa_log("Failed to create thread.");
527 pa_sink_put(u
->sink
);
542 int pa__get_n_used(pa_module
*m
) {
546 pa_assert_se(u
= m
->userdata
);
548 return pa_sink_linked_by(u
->sink
);
551 void pa__done(pa_module
*m
) {
556 if (!(u
= m
->userdata
))
560 pa_sink_unlink(u
->sink
);
563 pa_asyncmsgq_send(u
->thread_mq
.inq
, NULL
, PA_MESSAGE_SHUTDOWN
, NULL
, 0, NULL
);
564 pa_thread_free(u
->thread
);
567 pa_thread_mq_done(&u
->thread_mq
);
570 pa_sink_unref(u
->sink
);
572 if (u
->memchunk
.memblock
)
573 pa_memblock_unref(u
->memchunk
.memblock
);
576 pa_rtpoll_item_free(u
->rtpoll_item
);
579 pa_rtpoll_free(u
->rtpoll
);
588 static int alloc_gref(struct ioctl_gntalloc_alloc_gref
*gref_
, void **addr
) {
589 int alloc_fd
, dev_fd
, rv
;
591 alloc_fd
= open("/dev/xen/gntalloc", O_RDWR
);
593 perror("Could not open /dev/xen/gntalloc! Have you loaded the xen_gntalloc module?");
597 dev_fd
= open("/dev/xen/gntdev", O_RDWR
);
599 perror("Could not open /dev/xen/gntdev! Have you loaded the xen_gntdev module?");
605 gref_
->flags
= GNTALLOC_FLAG_WRITABLE
;
608 rv
= ioctl(alloc_fd
, IOCTL_GNTALLOC_ALLOC_GREF
, gref_
);
610 pa_log_debug("Xen audio sink: src-add error: %s (rv=%d)\n", strerror(errno
), rv
);
614 /*addr=NULL(default),length, prot, flags, fd, offset*/
615 *addr
= mmap(0, 4096, PROT_READ
|PROT_WRITE
, MAP_SHARED
, alloc_fd
, gref_
->index
);
616 if (*addr
== MAP_FAILED
) {
618 pa_log_debug("Xen audio sink: mmap'ing shared page failed\n");
622 pa_log_debug("Xen audio sink: Got grant #%d. Mapped locally at %Ld=%p\n",
623 gref_
->gref_ids
[0], (long long)gref_
->index
, *addr
);
626 struct ioctl_gntalloc_unmap_notify uarg = {
627 .index = gref->index + offsetof(struct shr_page, notifies[0]),
628 .action = UNMAP_NOTIFY_CLEAR_BYTE
631 rv = ioctl(a_fd, IOCTL_GNTALLOC_SET_UNMAP_NOTIFY, &uarg);
633 pa_log_debug("gntalloc unmap notify error: %s (rv=%d)\n", strerror(errno), rv);
642 #define RING_FREE_BYTES ((r->usable_buffer_space - (r->prod_indx-r->cons_indx) -1) % r->usable_buffer_space)
643 static int ring_write(struct ring
*r
, void *src
, int length
) {
646 /* free space may be split over the end of the buffer */
647 int first_chunk_size
= (r
->usable_buffer_space
-r
->prod_indx
);
648 int second_chunk_size
= (r
->cons_indx
>=r
->prod_indx
)? (r
->cons_indx
) : 0;
652 if (RING_FREE_BYTES
==0) {
660 /* should return in 100ms max; definitely not midstream */
665 /* calculate lengths in case of a split buffer */
666 l
= PA_MIN((int)RING_FREE_BYTES
, length
);
667 fl
= PA_MIN(l
, first_chunk_size
);
668 sl
= PA_MIN(l
-fl
, second_chunk_size
);
670 memcpy(r
->buffer
+r
->prod_indx
, src
, fl
);
672 memcpy(r
->buffer
, ((char*)src
)+fl
, sl
);
673 r
->prod_indx
= (r
->prod_indx
+fl
+sl
) % r
->usable_buffer_space
;
679 static int publish_param(const char *paramname
, const char *value
) {
680 char keybuf
[128], valbuf
[32];
682 snprintf(keybuf
, sizeof keybuf
, "device/audio/%d/%s", device_id
, paramname
);
683 snprintf(valbuf
, sizeof valbuf
, "%s", value
);
684 return xs_write(xsh
, 0, keybuf
, valbuf
, strlen(valbuf
));
687 static int publish_param_int(const char *paramname
, const int value
) {
688 char keybuf
[128], valbuf
[32];
689 snprintf(keybuf
, sizeof keybuf
, "device/audio/%d/%s", device_id
, paramname
);
690 snprintf(valbuf
, sizeof valbuf
, "%d", value
);
691 return xs_write(xsh
, 0, keybuf
, valbuf
, strlen(valbuf
));
694 static char* read_param(const char *paramname
) {
699 my_domid
= atoi(xs_read(xsh
, 0, "domid", &len
));
700 snprintf(keybuf
, sizeof(keybuf
), "/local/domain/0/backend/audio/%d/%d/%s", my_domid
, device_id
, paramname
);
701 /* remember to free lvalue! */
702 return xs_read(xsh
, 0, keybuf
, &len
);
706 static int publish_spec(pa_sample_spec
*sample_spec
) {
707 /* Publish spec and set state to XenbusStateInitWait*/
710 ret
= publish_param("format", pa_sample_format_to_string(sample_spec
->format
));
711 ret
+= publish_param_int("rate", sample_spec
->rate
);
712 ret
+= publish_param_int("channels", sample_spec
->channels
);
718 static int read_backend_default_spec(pa_sample_spec
*sample_spec
) {
719 /* Read spec from backend */
722 out
= read_param("default-format");
723 sample_spec
->format
= pa_parse_sample_format(out
);
726 out
= read_param("default-rate");
727 sample_spec
->rate
= atoi(out
);
730 out
= read_param("default-channels");
731 sample_spec
->channels
= atoi(out
);
737 static int register_backend_state_watch() {
742 my_domid
= atoi(xs_read(xsh
, 0, "domid", &len
));
743 snprintf(keybuf
, sizeof(keybuf
), "/local/domain/0/backend/audio/%d/%d/state", my_domid
, device_id
);
744 if (!xs_watch(xsh
, keybuf
, "xenpvaudiofrontendsinktoken")) {
745 perror("xs_watch failed");
751 static int wait_for_backend_state_change() {
766 backend_state
= STATE_UNDEFINED
;
767 xs_fd
= xs_fileno(xsh
);
768 start
= now
= time(NULL
);
770 my_domid
= atoi(xs_read(xsh
, 0, "domid", &len
));
771 snprintf(keybuf
, sizeof(keybuf
), "/local/domain/0/backend/audio/%d/%d/state", my_domid
, device_id
);
777 tv
.tv_sec
= (start
+ seconds
) - now
;
778 FD_ZERO(&watch_fdset
);
779 FD_SET(xs_fd
, &watch_fdset
);
780 ret
=select(xs_fd
+ 1, &watch_fdset
, NULL
, NULL
, &tv
);
787 /* Read the watch to drain the buffer */
788 vec
= xs_read_watch(xsh
, &len
);
790 buf
= xs_read(xsh
, XBT_NULL
, vec
[0], &len
);
792 /* usually means that the backend isn't there yet */
795 backend_state
= atoi(buf
);
801 } while (backend_state
== STATE_UNDEFINED
&& \
802 (now
= time(NULL
)) < start
+ seconds
);
804 return backend_state
;