From cd484fa9e490d37cb1781d1ae35b10e30551be42 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Wed, 23 Jun 2021 08:50:40 +0200
Subject: [PATCH] move repository to Debian's GitLab

---
 .gitignore                                    |    6 -
 98-osscuse.rules                              |    7 -
 LICENSE                                       |  339 ---
 Makefile                                      |   68 -
 README                                        |  120 +-
 debian/changelog                              |  104 -
 debian/control                                |   61 -
 debian/copyright                              |   52 -
 debian/osspd-alsa.install                     |    1 -
 debian/osspd-alsa.postinst                    |    9 -
 debian/osspd-alsa.prerm                       |   10 -
 debian/osspd-pulseaudio.install               |    1 -
 debian/osspd-pulseaudio.postinst              |    9 -
 debian/osspd-pulseaudio.prerm                 |   10 -
 debian/osspd.8                                |   68 -
 debian/osspd.docs                             |    1 -
 debian/osspd.init                             |  105 -
 debian/osspd.install                          |    2 -
 debian/osspd.kmod                             |    2 -
 debian/osspd.manpages                         |    1 -
 debian/osspd.modprobe                         |    3 -
 debian/osspd.service                          |    9 -
 ...pilation-with-Werror-format-security.patch |   45 -
 debian/patches/0002-honor-CPPFLAGS.patch      |   22 -
 ...ers-not-to-be-in-the-audio-group-so-.patch |   26 -
 ...ve-installation-path-during-compilat.patch |   85 -
 ...Add-pthread-compiler-and-linker-flag.patch |   26 -
 debian/patches/0006-fix-build-on-MIPS.patch   |   20 -
 debian/patches/0007-cross.patch               |   54 -
 debian/patches/GIT-fix-adsp_se.patch          |   24 -
 .../patches/GIT-fix-compiler-warnings.patch   |  251 --
 .../Hack-to-work-with-modern-PulseAudio.patch |   37 -
 debian/patches/series                         |   10 -
 debian/rules                                  |   24 -
 debian/source/format                          |    1 -
 debian/watch                                  |    2 -
 ossp-alsap.c                                  |  592 -----
 ossp-padsp.c                                  | 1524 -----------
 ossp-slave.c                                  |  250 --
 ossp-slave.h                                  |   28 -
 ossp-util.c                                   |  369 ---
 ossp-util.h                                   |  609 -----
 ossp.c                                        |   83 -
 ossp.h                                        |  117 -
 osspd.c                                       | 2295 -----------------
 osstest.c                                     |  266 --
 46 files changed, 1 insertion(+), 7747 deletions(-)
 delete mode 100644 .gitignore
 delete mode 100644 98-osscuse.rules
 delete mode 100644 LICENSE
 delete mode 100644 Makefile
 delete mode 100644 debian/changelog
 delete mode 100644 debian/control
 delete mode 100644 debian/copyright
 delete mode 100644 debian/osspd-alsa.install
 delete mode 100644 debian/osspd-alsa.postinst
 delete mode 100644 debian/osspd-alsa.prerm
 delete mode 100644 debian/osspd-pulseaudio.install
 delete mode 100644 debian/osspd-pulseaudio.postinst
 delete mode 100644 debian/osspd-pulseaudio.prerm
 delete mode 100644 debian/osspd.8
 delete mode 100644 debian/osspd.docs
 delete mode 100644 debian/osspd.init
 delete mode 100644 debian/osspd.install
 delete mode 100644 debian/osspd.kmod
 delete mode 100644 debian/osspd.manpages
 delete mode 100644 debian/osspd.modprobe
 delete mode 100644 debian/osspd.service
 delete mode 100644 debian/patches/0001-Fix-compilation-with-Werror-format-security.patch
 delete mode 100644 debian/patches/0002-honor-CPPFLAGS.patch
 delete mode 100644 debian/patches/0003-PA-recommends-users-not-to-be-in-the-audio-group-so-.patch
 delete mode 100644 debian/patches/0004-Allow-to-set-slave-installation-path-during-compilat.patch
 delete mode 100644 debian/patches/0005-Add-pthread-compiler-and-linker-flag.patch
 delete mode 100644 debian/patches/0006-fix-build-on-MIPS.patch
 delete mode 100644 debian/patches/0007-cross.patch
 delete mode 100644 debian/patches/GIT-fix-adsp_se.patch
 delete mode 100644 debian/patches/GIT-fix-compiler-warnings.patch
 delete mode 100644 debian/patches/Hack-to-work-with-modern-PulseAudio.patch
 delete mode 100644 debian/patches/series
 delete mode 100755 debian/rules
 delete mode 100644 debian/source/format
 delete mode 100644 debian/watch
 delete mode 100644 ossp-alsap.c
 delete mode 100644 ossp-padsp.c
 delete mode 100644 ossp-slave.c
 delete mode 100644 ossp-slave.h
 delete mode 100644 ossp-util.c
 delete mode 100644 ossp-util.h
 delete mode 100644 ossp.c
 delete mode 100644 ossp.h
 delete mode 100644 osspd.c
 delete mode 100644 osstest.c

diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index b578114..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-*.[oa]
-*~
-ossp-alsap
-ossp-padsp
-osspd
-osstest
diff --git a/98-osscuse.rules b/98-osscuse.rules
deleted file mode 100644
index c1430fd..0000000
--- a/98-osscuse.rules
+++ /dev/null
@@ -1,7 +0,0 @@
-# Since these devices are not part of 'sound' subsystem the group is forced
-# to audio by name
-# /dev/cuse can stay  mode 0660 root:root since osspd is run as root
-# and drops privileges to user level when opened by user
-KERNEL=="dsp", GROUP="audio"
-KERNEL=="mixer", GROUP="audio"
-KERNEL=="adsp", GROUP="audio"
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index d511905..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,339 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 8111c9b..0000000
--- a/Makefile
+++ /dev/null
@@ -1,68 +0,0 @@
-# These can be overridden if needed
-# DESTDIR is completely respected
-CC := gcc
-AR := ar
-CFLAGS := -Wall $(CFLAGS)
-XLDFLAGS := $(LDFLAGS)
-LDFLAGS := -L. -lossp $(LDFLAGS)
-prefix := /usr/local
-DESTDIR :=
-UDEVDIR := /etc/udev/rules.d
-
-ifeq "$(origin OSSPD_CFLAGS)" "undefined"
-OSSPD_CFLAGS := $(shell pkg-config --cflags fuse)
-endif
-
-ifeq "$(origin OSSPD_LDFLAGS)" "undefined"
-OSSPD_LDFLAGS := $(shell pkg-config --libs fuse)
-endif
-
-ifeq "$(origin OSSP_PADSP_CFLAGS)" "undefined"
-OSSP_PADSP_CFLAGS := $(shell pkg-config --cflags libpulse)
-endif
-
-ifeq "$(origin OSSP_PADSP_LDFLAGS)" "undefined"
-OSSP_PADSP_LDFLAGS := $(shell pkg-config --libs libpulse)
-endif
-
-ifeq "$(origin OSSP_ALSAP_CFLAGS)" "undefined"
-OSSP_ALSAP_CFLAGS := $(shell pkg-config --libs alsa)
-endif
-
-ifeq "$(origin OSSP_ALSAP_LDFLAGS)" "undefined"
-OSSP_ALSAP_LDFLAGS := $(shell pkg-config --libs alsa)
-endif
-
-headers := ossp.h ossp-util.h ossp-slave.h
-
-all: osspd ossp-padsp ossp-alsap
-
-install:
-	mkdir -p $(DESTDIR)$(prefix)/sbin
-	install -m755 osspd ossp-padsp ossp-alsap $(DESTDIR)$(prefix)/sbin
-	mkdir -p $(DESTDIR)$(UDEVDIR)
-	install -m644 98-osscuse.rules $(DESTDIR)$(UDEVDIR)
-
-libossp.a: ossp.c ossp.h ossp-util.c ossp-util.h ossp-slave.c ossp-slave.h
-	$(CC) $(CFLAGS) -c -o ossp.o ossp.c
-	$(CC) $(CFLAGS) -c -o ossp-util.o ossp-util.c
-	$(CC) $(CFLAGS) -c -o ossp-slave.o ossp-slave.c
-	$(AR) rc $@ ossp.o ossp-util.o ossp-slave.o
-
-osspd: osspd.c libossp.a $(headers)
-	$(CC) $(CFLAGS) $(OSSPD_CFLAGS) -o $@ $< $(OSSPD_LDFLAGS) $(LDFLAGS)
-
-ossp-padsp: ossp-padsp.c libossp.a $(headers)
-	$(CC) $(CFLAGS) $(OSSP_PADSP_CFLAGS) -o $@ $< $(OSSP_PADSP_LDFLAGS) $(LDFLAGS)
-
-ossp-alsap: ossp-alsap.c libossp.a $(headers)
-	$(CC) $(CFLAGS) $(OSSP_ALSAP_CFLAGS) -o $@ $< $(OSSP_ALSAP_LDFLAGS) $(LDFLAGS)
-
-osstest: osstest.c
-	$(CC) $(CFLAGS) -o $@ $< $(XLDFLAGS)
-
-test: osstest
-	@./osstest
-
-clean:
-	rm -f *.o *.a osspd ossp-padsp ossp-alsap osstest
diff --git a/README b/README
index 6b716c7..a56aa1b 100644
--- a/README
+++ b/README
@@ -1,119 +1 @@
-
- OSS Proxy - emulate OSS device using CUSE
-
- Copyright (C) 2008-2009  SUSE Linux Products GmbH
- Copyright (C) 2008-2009  Tejun Heo <tj@kernel.org>
-
-1. What is it?
---------------
-
-Well, first, OSS refers to Open Sound System.  If it still doesn't
-ring a bell, think /dev/dsp, /dev/adsp and /dev/mixer.
-
-Currently, Linux supports two audio programming interface - ALSA and
-OSS.  The latter one is deprecated and has been that way for a long
-time but there still are applications which still use them including
-UML (usermode Linux) host sound support.
-
-ALSA contains OSS emulation but sadly the emulation is behind
-multiplexing layer (which is in userland) which means that if your
-sound card doesn't support multiple audio streams, only either one of
-ALSA or OSS interface would be usable at any given moment.
-
-There have been also attempts to emulate OSS in userland using dynamic
-library preloading - aoss and more recently padsp.  This works for
-many applications but it's just not easy to emulate everything using
-the technique.  Things like polling, signals, forking, privilege
-changes make it very difficult to emulate things reliably.
-
-OSS Proxy uses CUSE (extension of FUSE allowing character devices to
-be implemented in userspace) to implement OSS interface - /dev/dsp,
-/dev/adsp and /dev/mixer.  From the POV of the applications, these
-devices are proper character devices and behave exactly the same way
-so it can be made quite versatile.
-
-
-2. Hmmm... So, how does the whole thing work?
----------------------------------------------
-
-The OSS Proxy daemon - osspd - should be started first.  Note that
-osspd will fail to start if sound device number regions are already
-occupied.  You'll need to turn off OSS or its emulation[1].
-
-On startup, osspd creates /dev/dsp, /dev/adsp and /dev/mixer using
-CUSE.  When an application access one of the devices, all IOs are
-redirected to osspd via CUSE.  Upon receiving a new DSP open request,
-osspd creates a slave process which drops the root privilege and
-assumes the opening process's credentials.  After handshaking, osspd
-forwards all relevant IOs to the slave which is responsible for
-actually playing the sound.
-
-Currently there's only one slave implemented - ossp-padsp, which as
-the name suggests forwards (again) the sound to pulseaudio.  To sum
-up, the whole pipe looks like the following.
-
- App <-> /dev/dsp <-> CUSE <-> osspd <-> ossp-padsp <-> pulseaudio
-
-Which is a lot of forwarding, but on modern machines, it won't be too
-noticeable.
-
-
-3. What works?
---------------
-
-Well, MIDI part isn't implemented and I doubt it will be in any near
-future but except that everything should work.  Playing, recording,
-5.1ch, A-V syncing, all should work.  If not, it's a bug, so please
-report.
-
-The mixer behaves a bit differently tho.  In the original OSS,
-/dev/mixer is the hardware mixer, so adjusting volumes there affects
-all audio streams.  When using ossp, each process group gets its own
-mixer and the mixer always contains only two knobs - PCM and IGAIN.
-Combined with per-stream volume control of pulseaudio, this scheme
-works quite well for applications with embedded volume control
-although it makes standalone OSS mixer programs virtually useless[2].
-
-
-4. How do I use it?
--------------------
-
-First you need CUSE support in kernel which might land on 2.6.28 with
-sufficient luck[3] and then you also need libfuse which supports
-CUSE[4].  Once you have both, it should be easy.  First build it by
-running `make'.  You can set OSSPD_CFLAGS, OSSPD_LDFLAGS,
-OSSP_PADSP_CFLAGS and OSSP_PADSP_LDFLAGS if you have stuff at
-non-default locations.
-
-After build completes, there will be two executables - `osspd' and
-`ossp-padsp'.  Just copy them to where other system executables live.
-Specific location doesn't matter as long as both files end up in the
-same directory.
-
-Execute `osspd'.  It will create the device files and you're all set.
-`osspd' uses syslog with LOG_DAEMON facility, so if something doesn't
-work take a look at what osspd complains about.
-
-
-[1] As of this writing, turning on any sound support makes the
-    soundcore module claim OSS device regions.  Patch to make it claim
-    OSS device regions only when OSS support or emulation is enabled
-    is scheduled for 2.6.28.  Even with the patch, soundcore will
-    claim OSS device regions if OSS support or ALSA OSS emulation is
-    enabled.  Make sure they're turned off.
-
-[2] If you have a strong reason to use standalone OSS mixer program,
-    you can play some shell tricks to put it into the same process
-    group as the target audio application.  e.g. To use aumix with
-    mpg123 - `(mpg123 asdf.mp3 > /dev/null 2>&1 & aumix)', but
-    seriously, just use PA or ALSA one.
-
-[3] For the time being, here's the git tree with all the necessary
-    changes.  This tree is base on top of 2.6.27-rc3.
-
-    http://git.kernel.org/?p=linux/kernel/git/tj/misc.git;a=shortlog;h=cuse
-    git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git cuse
-
-[4] And libfuse with the modifications can be found at...
-
-    http://userweb.kernel.org/~tj/ossp/fuse-cuse.tar.gz
+This repository moved to https://salsa.debian.org/debian/osspd
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 9481d07..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,104 +0,0 @@
-osspd (1.3.2-12) unstable; urgency=low
-
-  [ Sébastien Noel ]
-  * cherrypick 2 commits from upstream GIT:
-    + d/p/GIT-fix-adsp_se.patch
-    + d/p/GIT-fix-compiler-warnings.patch
-  * Add workaround for pulseaudio >= 13
-    d/p/Hack-to-work-with-modern-PulseAudio.patch  (Closes: #986662)
-
-  [ Ralf Jung ]
-  * Switch to debhelper compat level 13.
-
- -- Ralf Jung <post@ralfj.de>  Sat, 17 Apr 2021 14:28:09 +0200
-
-osspd (1.3.2-11) unstable; urgency=medium
-
-  * Update Standards-Version to 4.3.0.  No changes needed.
-  * Fix cross-build with a patch by Helmut Grohne
-    <helmut@subdivi.de> (again).  (Closes: #917827).
-
- -- Ralf Jung <post@ralfj.de>  Fri, 25 Jan 2019 15:36:20 +0100
-
-osspd (1.3.2-10) unstable; urgency=medium
-
-  * Fix build on MIPS.  (Closes: #916231)
-
- -- Ralf Jung <post@ralfj.de>  Wed, 26 Dec 2018 19:10:03 +0100
-
-osspd (1.3.2-9) unstable; urgency=medium
-
-  * Fix using target-architecture pkg-config. Patch by
-    Helmut Grohne <helmut@subdivi.de>.  (Closes: #882365)
-  * No longer depend on obsolete dh-systemd.  Instead, depend
-    on sufficiently new debhelper.
-  * Update Standards-Version to 4.1.2.  Changed some URLs to
-    https.
-
- -- Ralf Jung <post@ralfj.de>  Fri, 08 Dec 2017 19:56:38 +0100
-
-osspd (1.3.2-8) unstable; urgency=medium
-
-  * Mark osspd as Multi-Arch: foreign (Closes: #861577).
-  * Update Standards-Version to 3.9.8. No changes needed.
-  * Use https URL for Vcs-Browser.
-  * Add Documentation to systemd service file.
-  * Fix a typo in the manpage.
-
- -- Ralf Jung <post@ralfj.de>  Wed, 17 May 2017 19:31:18 +0200
-
-osspd (1.3.2-7) unstable; urgency=medium
-
-  * Migrate debug symbols to ddeb.
-  * Update Standards-Version to 3.9.6. No changes needed.
-
- -- Ralf Jung <post@ralfj.de>  Mon, 28 Dec 2015 13:39:48 +0100
-
-osspd (1.3.2-6) unstable; urgency=medium
-
-  * Load cuse module via module-load.d.
-  * Update Standards-Version to 3.9.5. No changes needed.
-
- -- Ralf Jung <post@ralfj.de>  Mon, 31 Mar 2014 17:36:52 +0200
-
-osspd (1.3.2-5) unstable; urgency=low
-
-  * Fix systemd service file.
-
- -- Ralf Jung <post@ralfj.de>  Thu, 10 Oct 2013 18:29:28 +0200
-
-osspd (1.3.2-4) unstable; urgency=low
-
-  * Move backends into their own packages.
-  * Manage the ossp slave via update-alternatives.
-  * Add a systemd service file (taken from Arch).
-  * Add modprobe file to blacklist OSS modules - thanks, Stephen
-    (Closes: #712705).
-
- -- Ralf Jung <post@ralfj.de>  Thu, 26 Sep 2013 22:28:08 +0200
-
-osspd (1.3.2-3) unstable; urgency=low
-
-  * Provide oss-compat, as we provide OSS, and conflict with it
-    since it takes the OSS major/minor numbers.
-  * Update Standards-Version to 3.9.4. No changes needed.
-  * Add "-pthreads" compiler and linker flag. Patch based on Ubuntu
-    patch by Logan Rosen <logan@ubuntu.com>.
-  * Add links to git repository.
-
- -- Ralf Jung <post@ralfj.de>  Sat, 18 May 2013 18:18:14 +0200
-
-osspd (1.3.2-2) unstable; urgency=low
-
-  * 0004-Allow-to-set-slave-installation-path-during-compilat.patch:
-    Removed unused variables.
-  * Change architecture to linux-any as Hurd and FreeBSD lack epoll.
-  * Extend package description.
-
- -- Ralf Jung <post@ralfj.de>  Tue, 02 Oct 2012 13:26:56 +0200
-
-osspd (1.3.2-1) unstable; urgency=low
-
-  * Initial release (Closes: #687711).
-
- -- Ralf Jung <post@ralfj.de>  Thu, 20 Sep 2012 11:07:39 +0200
diff --git a/debian/control b/debian/control
deleted file mode 100644
index ee044ca..0000000
--- a/debian/control
+++ /dev/null
@@ -1,61 +0,0 @@
-Source: osspd
-Section: sound
-Priority: optional
-Maintainer: Ralf Jung <post@ralfj.de>
-Uploaders: Sébastien Noel <sebastien@twolife.be>
-Build-Depends: debhelper-compat (= 13),
-               libasound2-dev,
-               libfuse-dev,
-               libpulse-dev
-Standards-Version: 4.3.0
-Homepage: https://sourceforge.net/projects/osspd/
-Vcs-Browser: https://git.ralfj.de/osspd.git
-Vcs-Git: git://ralfj.de/osspd.git
-
-Package: osspd
-Architecture: linux-any
-Multi-Arch: foreign
-Pre-Depends: ${misc:Pre-Depends}
-Depends: lsb-base (>= 3.2-14),
-         osspd-pulseaudio | osspd-backend,
-         ${misc:Depends},
-         ${shlibs:Depends}
-Provides: oss-compat
-Conflicts: oss-compat
-Description: OSS Proxy Daemon: Userland OSS emulation
- OSS Proxy Daemon is a Linux userland OSS sound device (/dev/[a]dsp and
- /dev/mixer) implementation using CUSE. Currently it supports
- forwarding OSS sound streams to PulseAudio and ALSA.
- .
- Actually emulating the OSS devices makes for a more robust emulation compared
- to OSS wrappers using LD_PRELOAD, like aoss and padsp. It also works better
- when running foreign-architecture applications or using old libc versions for
- compatibility reasons.
-
-Package: osspd-pulseaudio
-Architecture: linux-any
-Provides: osspd-backend
-Depends: pulseaudio, ${misc:Depends}, ${shlibs:Depends}
-Recommends: osspd
-Replaces: osspd (<< 1.3.2-4)
-Breaks: osspd (<< 1.3.2-4)
-Description: OSS Proxy Daemon: PulseAudio backend
- OSS Proxy Daemon is a Linux userland OSS sound device (/dev/[a]dsp and
- /dev/mixer) implementation using CUSE. Currently it supports
- forwarding OSS sound streams to PulseAudio and ALSA.
- .
- This package contains the PulseAudio backend for osspd.
-
-Package: osspd-alsa
-Architecture: linux-any
-Provides: osspd-backend
-Depends: ${misc:Depends}, ${shlibs:Depends}
-Recommends: osspd
-Replaces: osspd (<< 1.3.2-4)
-Breaks: osspd (<< 1.3.2-4)
-Description: OSS Proxy Daemon: ALSA backend (experimental)
- OSS Proxy Daemon is a Linux userland OSS sound device (/dev/[a]dsp and
- /dev/mixer) implementation using CUSE. Currently it supports
- forwarding OSS sound streams to PulseAudio and ALSA.
- .
- This package contains the experimental ALSA backend for osspd.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index f0c752d..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,52 +0,0 @@
-Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: osspd
-Source: https://sourceforge.net/projects/osspd/
-
-Files: *
-Copyright: 2008-2010  SUSE Linux Products GmbH
-           2008-2010  Tejun Heo <tj@kernel.org>
-           2009       Maarten Lankhorst <m.b.lankhorst@gmail.com>
-License: GPL-2
-
-Files: debian/*
-Copyright: 2012-2013 Ralf Jung <post@ralfj.de>
-License: GPL-2+
-
-Files: debian/osspd.service
-Copyright: 2013 Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
-           2013 Ralf Jung <post@ralfj.de>
-License: GPL-2
-
-
-License: GPL-2
- This package is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
- .
- This package is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
- .
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>
- .
- On Debian systems, the complete text of the GNU General
- Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
-
-License: GPL-2+
- This package is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- .
- This package is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
- .
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>
- .
- On Debian systems, the complete text of the GNU General
- Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
diff --git a/debian/osspd-alsa.install b/debian/osspd-alsa.install
deleted file mode 100644
index 8b70aa6..0000000
--- a/debian/osspd-alsa.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/osspd/ossp-alsap
diff --git a/debian/osspd-alsa.postinst b/debian/osspd-alsa.postinst
deleted file mode 100644
index 64573ac..0000000
--- a/debian/osspd-alsa.postinst
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-set -e
-
-update-alternatives --install /usr/lib/osspd/ossp-slave \
-      ossp-slave /usr/lib/osspd/ossp-alsap 60
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/osspd-alsa.prerm b/debian/osspd-alsa.prerm
deleted file mode 100644
index fee2410..0000000
--- a/debian/osspd-alsa.prerm
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-set -e
-
-if [ "$1" = "remove" ]; then
-  update-alternatives --remove ossp-slave /usr/lib/osspd/ossp-alsap
-fi
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/osspd-pulseaudio.install b/debian/osspd-pulseaudio.install
deleted file mode 100644
index ccb91fa..0000000
--- a/debian/osspd-pulseaudio.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/osspd/ossp-padsp
diff --git a/debian/osspd-pulseaudio.postinst b/debian/osspd-pulseaudio.postinst
deleted file mode 100644
index 84e2f2a..0000000
--- a/debian/osspd-pulseaudio.postinst
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-set -e
-
-update-alternatives --install /usr/lib/osspd/ossp-slave \
-      ossp-slave /usr/lib/osspd/ossp-padsp 70
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/osspd-pulseaudio.prerm b/debian/osspd-pulseaudio.prerm
deleted file mode 100644
index 0f3c85d..0000000
--- a/debian/osspd-pulseaudio.prerm
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-set -e
-
-if [ "$1" = "remove" ]; then
-  update-alternatives --remove ossp-slave /usr/lib/osspd/ossp-padsp
-fi
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/osspd.8 b/debian/osspd.8
deleted file mode 100644
index c94bc78..0000000
--- a/debian/osspd.8
+++ /dev/null
@@ -1,68 +0,0 @@
-.TH OSSPD "8" "September 2012" "osspd 1.3.2"
-
-.SH NAME
-osspd \- OSS Proxy Daemon
-
-.SH SYNOPSIS
-\fBosspd\fR [\fIoptions\fR]
-
-.SH DESCRIPTION
-\fBosspd\fR implements the OSS devices (/dev/[a]dsp and /dev/mixer) in userland using CUSE.
-Sound data is forwarded to a DSP slave: Implementations for PulseAudio and ASLA exist, but the ALSA
-slave should still be considered experimental.
-
-.SH OPTIONS
-.TP
-\fB\-\-dsp\fR=\fINAME\fR
-DSP device name (default dsp)
-.TP
-\fB\-\-dsp\-maj\fR=\fIMAJ\fR
-DSP device major number (default 14)
-.TP
-\fB\-\-dsp\-min\fR=\fIMIN\fR
-DSP device minor number (default 3)
-.TP
-\fB\-\-adsp\fR=\fINAME\fR
-Aux DSP device name (default adsp, blank to disable)
-.TP
-\fB\-\-adsp\-maj\fR=\fIMAJ\fR
-Aux DSP device major number (default 14)
-.TP
-\fB\-\-adsp\-min\fR=\fIMIN\fR
-Aux DSP device minor number (default 12)
-.TP
-\fB\-\-mixer\fR=\fINAME\fR
-mixer device name (default mixer, blank to disable)
-.TP
-\fB\-\-mixer\-maj\fR=\fIMAJ\fR
-mixer device major number (default 14)
-.TP
-\fB\-\-mixer\-min\fR=\fIMIN\fR
-mixer device minor number (default 0)
-.TP
-\fB\-\-max\fR=\fIMAX\fR
-maximum number of open streams (default 256)
-.TP
-\fB\-\-umax\fR=\fIMAX\fR
-maximum number of open streams per UID (default \fB\-\-max\fR)
-.TP
-\fB\-\-exit\-on\-idle\fR
-exit if idle
-.TP
-\fB\-\-dsp\-slave\fR=\fIPATH\fR
-DSP slave (default ossp\-padsp in the same dir)
-.TP
-\fB\-\-log\fR=\fILEVEL\fR
-log level (0..6)
-.TP
-\fB\-\-timestamp\fR
-timestamp log messages
-.TP
-\fB\-v\fR
-increase verbosity, can be specified multiple times
-.TP
-\fB\-f\fR
-Run in foreground (don't daemonize)
-
-.SH "SEE ALSO"
-A more technical documentation describing some of the inner workings can be found at \fI/usr/share/doc/osspd/README.gz\fR.
diff --git a/debian/osspd.docs b/debian/osspd.docs
deleted file mode 100644
index e845566..0000000
--- a/debian/osspd.docs
+++ /dev/null
@@ -1 +0,0 @@
-README
diff --git a/debian/osspd.init b/debian/osspd.init
deleted file mode 100644
index 8669c76..0000000
--- a/debian/osspd.init
+++ /dev/null
@@ -1,105 +0,0 @@
-#! /bin/sh
-### BEGIN INIT INFO
-# Provides:          osspd
-# Required-Start:    $remote_fs $syslog
-# Required-Stop:     $remote_fs $syslog
-# Default-Start:     2 3 4 5
-# Default-Stop:      0 1 6
-# Short-Description: OSS Proxy Daemon: Userland OSS emulation
-# Description:       Daemon providing a userland implementation of OSS devices.
-#                    Currently it supports forwarding OSS sound streams to
-#                    PulseAudio and ALSA.
-### END INIT INFO
-
-# Author: Ralf Jung <post@ralfj.de>
-
-PATH=/sbin:/usr/sbin:/bin:/usr/bin
-DESC="OSS Proxy Daemon"
-NAME=osspd
-DAEMON=/usr/sbin/$NAME
-DAEMON_ARGS="--dsp-slave=/usr/lib/osspd/ossp-slave"
-PIDFILE=/var/run/$NAME.pid
-SCRIPTNAME=/etc/init.d/$NAME
-
-# Exit if the package is not installed
-[ -x "$DAEMON" ] || exit 0
-
-# Define LSB log_* functions.
-. /lib/lsb/init-functions
-
-#
-# Function that starts the daemon/service
-#
-do_start()
-{
-	# Return
-	#   0 if daemon has been started
-	#   1 if daemon was already running
-	#   2 if daemon could not be started
-	start-stop-daemon --start --background --quiet --pidfile $PIDFILE --make-pidfile --exec $DAEMON --test > /dev/null \
-		|| return 1
-	# -f: run in foreground, start-stop-daemon does the forking - this is required to let start-stop-daemon handle the pidfile
-	start-stop-daemon --start --background --quiet --pidfile $PIDFILE --make-pidfile --exec $DAEMON -- -f \
-		$DAEMON_ARGS \
-		|| return 2
-}
-
-#
-# Function that stops the daemon/service
-#
-do_stop()
-{
-	# Return
-	#   0 if daemon has been stopped
-	#   1 if daemon was already stopped
-	#   2 if daemon could not be stopped
-	#   other if a failure occurred
-	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
-	return "$?"
-}
-
-case "$1" in
-  start)
-	log_daemon_msg "Starting $DESC" "$NAME"
-	do_start
-	case "$?" in
-		0|1) log_end_msg 0 ;;
-		2) log_end_msg 1 ;;
-	esac
-	;;
-  stop)
-	log_daemon_msg "Stopping $DESC" "$NAME"
-	do_stop
-	case "$?" in
-		0|1) log_end_msg 0 ;;
-		2) log_end_msg 1 ;;
-	esac
-	;;
-  status)
-	status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
-	;;
-  restart|force-reload)
-	log_daemon_msg "Restarting $DESC" "$NAME"
-	do_stop
-	case "$?" in
-	  0|1)
-		do_start
-		case "$?" in
-			0) log_end_msg 0 ;;
-			1) log_end_msg 1 ;; # Old process is still running
-			*) log_end_msg 1 ;; # Failed to start
-		esac
-		;;
-	  *)
-		# Failed to stop
-		log_end_msg 1
-		;;
-	esac
-	;;
-  *)
-	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
-	exit 3
-	;;
-esac
-
-:
diff --git a/debian/osspd.install b/debian/osspd.install
deleted file mode 100644
index ff410bf..0000000
--- a/debian/osspd.install
+++ /dev/null
@@ -1,2 +0,0 @@
-lib/udev/rules.d/98-osscuse.rules
-usr/sbin/osspd
diff --git a/debian/osspd.kmod b/debian/osspd.kmod
deleted file mode 100644
index e1bacaf..0000000
--- a/debian/osspd.kmod
+++ /dev/null
@@ -1,2 +0,0 @@
-# Load cuse module for osspd
-cuse
diff --git a/debian/osspd.manpages b/debian/osspd.manpages
deleted file mode 100644
index a289ff0..0000000
--- a/debian/osspd.manpages
+++ /dev/null
@@ -1 +0,0 @@
-debian/osspd.8
diff --git a/debian/osspd.modprobe b/debian/osspd.modprobe
deleted file mode 100644
index 45d8163..0000000
--- a/debian/osspd.modprobe
+++ /dev/null
@@ -1,3 +0,0 @@
-blacklist snd-pcm-oss
-blacklist snd-mixer-oss
-blacklist snd-seq-oss
diff --git a/debian/osspd.service b/debian/osspd.service
deleted file mode 100644
index 5f35e2d..0000000
--- a/debian/osspd.service
+++ /dev/null
@@ -1,9 +0,0 @@
-[Unit]
-Description=OSS Proxy Daemon
-Documentation=man:osspd
-
-[Service]
-ExecStart=/usr/sbin/osspd -f --dsp-slave=/usr/lib/osspd/ossp-slave
-
-[Install]
-WantedBy=multi-user.target
diff --git a/debian/patches/0001-Fix-compilation-with-Werror-format-security.patch b/debian/patches/0001-Fix-compilation-with-Werror-format-security.patch
deleted file mode 100644
index 085274f..0000000
--- a/debian/patches/0001-Fix-compilation-with-Werror-format-security.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From: Ralf Jung <post@ralfj.de>
-Date: Sat, 15 Sep 2012 13:36:06 +0200
-Subject: Fix compilation with -Werror=format-security
-
-Forwarded: Committed upstream as 097dc7b6
----
- ossp-slave.c | 4 ++--
- osspd.c      | 2 +-
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/ossp-slave.c b/ossp-slave.c
-index 4c5cb2d..a290636 100644
---- a/ossp-slave.c
-+++ b/ossp-slave.c
-@@ -89,7 +89,7 @@ void ossp_slave_init(int argc, char **argv)
- 	}
- 
- 	if (!have_uid || !have_gid || ossp_cmd_fd < 0 || ossp_notify_fd < 0) {
--		fprintf(stderr, usage);
-+		fputs(usage, stderr);
- 		_exit(1);
- 	}
- 
-@@ -105,7 +105,7 @@ void ossp_slave_init(int argc, char **argv)
- 		void *p;
- 
- 		if (!mmap_off || !mmap_size) {
--			fprintf(stderr, usage);
-+			fputs(usage, stderr);
- 			_exit(1);
- 		}
- 
-diff --git a/osspd.c b/osspd.c
-index 37c9b35..1dbe586 100644
---- a/osspd.c
-+++ b/osspd.c
-@@ -2109,7 +2109,7 @@ static int process_arg(void *data, const char *arg, int key,
- 
- 	switch (key) {
- 	case 0:
--		fprintf(stderr, usage);
-+		fputs(usage, stderr);
- 		param->help = 1;
- 		return 0;
- 	case 1:
diff --git a/debian/patches/0002-honor-CPPFLAGS.patch b/debian/patches/0002-honor-CPPFLAGS.patch
deleted file mode 100644
index e073ad9..0000000
--- a/debian/patches/0002-honor-CPPFLAGS.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From: Ralf Jung <post@ralfj.de>
-Date: Sat, 15 Sep 2012 13:36:23 +0200
-Subject: honor CPPFLAGS
-
-Forwarded: Committed upstream as 3a9a0196
----
- Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/Makefile b/Makefile
-index 8111c9b..8d8fe87 100644
---- a/Makefile
-+++ b/Makefile
-@@ -2,7 +2,7 @@
- # DESTDIR is completely respected
- CC := gcc
- AR := ar
--CFLAGS := -Wall $(CFLAGS)
-+CFLAGS := -Wall $(CFLAGS) $(CPPFLAGS)
- XLDFLAGS := $(LDFLAGS)
- LDFLAGS := -L. -lossp $(LDFLAGS)
- prefix := /usr/local
diff --git a/debian/patches/0003-PA-recommends-users-not-to-be-in-the-audio-group-so-.patch b/debian/patches/0003-PA-recommends-users-not-to-be-in-the-audio-group-so-.patch
deleted file mode 100644
index 4844721..0000000
--- a/debian/patches/0003-PA-recommends-users-not-to-be-in-the-audio-group-so-.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From: Ralf Jung <post@ralfj.de>
-Date: Thu, 13 Sep 2012 19:13:25 +0200
-Subject: PA recommends users *not* to be in the audio group,
- so allow everyone to use these devices
-
-Forwarded: not-needed
----
- 98-osscuse.rules | 9 ++++-----
- 1 file changed, 4 insertions(+), 5 deletions(-)
-
-diff --git a/98-osscuse.rules b/98-osscuse.rules
-index c1430fd..9b40bec 100644
---- a/98-osscuse.rules
-+++ b/98-osscuse.rules
-@@ -1,7 +1,6 @@
--# Since these devices are not part of 'sound' subsystem the group is forced
--# to audio by name
-+# Allow everyone to use these devices
- # /dev/cuse can stay  mode 0660 root:root since osspd is run as root
- # and drops privileges to user level when opened by user
--KERNEL=="dsp", GROUP="audio"
--KERNEL=="mixer", GROUP="audio"
--KERNEL=="adsp", GROUP="audio"
-+KERNEL=="dsp", SUBSYSTEM=="cuse", MODE="0666"
-+KERNEL=="mixer", SUBSYSTEM=="cuse", MODE="0666"
-+KERNEL=="adsp", SUBSYSTEM=="cuse", MODE="0666"
diff --git a/debian/patches/0004-Allow-to-set-slave-installation-path-during-compilat.patch b/debian/patches/0004-Allow-to-set-slave-installation-path-during-compilat.patch
deleted file mode 100644
index 59425c9..0000000
--- a/debian/patches/0004-Allow-to-set-slave-installation-path-during-compilat.patch
+++ /dev/null
@@ -1,85 +0,0 @@
-From: Ralf Jung <post@ralfj.de>
-Date: Wed, 19 Sep 2012 13:12:58 +0200
-Subject: Allow to set slave installation path during compilation
-
-Forwarded: not-needed
----
- Makefile |  8 +++++---
- osspd.c  | 12 ++----------
- 2 files changed, 7 insertions(+), 13 deletions(-)
-
-diff --git a/Makefile b/Makefile
-index 8d8fe87..236176e 100644
---- a/Makefile
-+++ b/Makefile
-@@ -8,6 +8,7 @@ LDFLAGS := -L. -lossp $(LDFLAGS)
- prefix := /usr/local
- DESTDIR :=
- UDEVDIR := /etc/udev/rules.d
-+SLAVESDIR := $(prefix)/sbin
- 
- ifeq "$(origin OSSPD_CFLAGS)" "undefined"
- OSSPD_CFLAGS := $(shell pkg-config --cflags fuse)
-@@ -38,8 +39,9 @@ headers := ossp.h ossp-util.h ossp-slave.h
- all: osspd ossp-padsp ossp-alsap
- 
- install:
--	mkdir -p $(DESTDIR)$(prefix)/sbin
--	install -m755 osspd ossp-padsp ossp-alsap $(DESTDIR)$(prefix)/sbin
-+	mkdir -p $(DESTDIR)$(prefix)/sbin $(DESTDIR)$(SLAVESDIR)
-+	install -m755 osspd $(DESTDIR)$(prefix)/sbin
-+	install -m755 ossp-padsp ossp-alsap $(DESTDIR)$(SLAVESDIR)
- 	mkdir -p $(DESTDIR)$(UDEVDIR)
- 	install -m644 98-osscuse.rules $(DESTDIR)$(UDEVDIR)
- 
-@@ -50,7 +52,7 @@ libossp.a: ossp.c ossp.h ossp-util.c ossp-util.h ossp-slave.c ossp-slave.h
- 	$(AR) rc $@ ossp.o ossp-util.o ossp-slave.o
- 
- osspd: osspd.c libossp.a $(headers)
--	$(CC) $(CFLAGS) $(OSSPD_CFLAGS) -o $@ $< $(OSSPD_LDFLAGS) $(LDFLAGS)
-+	$(CC) $(CFLAGS) $(OSSPD_CFLAGS) -DSLAVE_DEFAULT_PATH=\"$(SLAVESDIR)\" -o $@ $< $(OSSPD_LDFLAGS) $(LDFLAGS)
- 
- ossp-padsp: ossp-padsp.c libossp.a $(headers)
- 	$(CC) $(CFLAGS) $(OSSP_PADSP_CFLAGS) -o $@ $< $(OSSP_PADSP_LDFLAGS) $(LDFLAGS)
-diff --git a/osspd.c b/osspd.c
-index 1dbe586..6b63c07 100644
---- a/osspd.c
-+++ b/osspd.c
-@@ -2005,7 +2005,7 @@ static const char *usage =
- "    --max=MAX         maximum number of open streams (default 256)\n"
- "    --umax=MAX        maximum number of open streams per UID (default --max)\n"
- "    --exit-on-idle    exit if idle\n"
--"    --dsp-slave=PATH  DSP slave (default ossp-padsp in the same dir)\n"
-+"    --dsp-slave=PATH  DSP slave (default: " SLAVE_DEFAULT_PATH "/ossp-padsp)\n"
- "    --log=LEVEL       log level (0..6)\n"
- "    --timestamp       timestamp log messages\n"
- "    -v                increase verbosity, can be specified multiple times\n"
-@@ -2131,7 +2131,6 @@ int main(int argc, char **argv)
- 		.max_streams = DFL_MAX_STREAMS,
- 	};
- 	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
--	char path_buf[PATH_MAX], *dir;
- 	char adsp_buf[64] = "", mixer_buf[64] = "";
- 	struct sigaction sa;
- 	struct stat stat_buf;
-@@ -2175,19 +2174,12 @@ int main(int argc, char **argv)
- 	if (sigaction(SIGPIPE, &sa, NULL))
- 		fatal_e(-errno, "failed to ignore SIGPIPE");
- 
--	/* determine slave path and check for availability */
--	ret = readlink("/proc/self/exe", path_buf, PATH_MAX - 1);
--	if (ret < 0)
--		fatal_e(-errno, "failed to determine executable path");
--	path_buf[ret] = '\0';
--	dir = dirname(path_buf);
--
- 	if (param.dsp_slave_path) {
- 		strncpy(dsp_slave_path, param.dsp_slave_path, PATH_MAX - 1);
- 		dsp_slave_path[PATH_MAX - 1] = '\0';
- 	} else {
- 		ret = snprintf(dsp_slave_path, PATH_MAX, "%s/%s",
--			       dir, "ossp-padsp");
-+			       SLAVE_DEFAULT_PATH, "ossp-padsp");
- 		if (ret >= PATH_MAX)
- 			fatal("dsp slave pathname too long");
- 	}
diff --git a/debian/patches/0005-Add-pthread-compiler-and-linker-flag.patch b/debian/patches/0005-Add-pthread-compiler-and-linker-flag.patch
deleted file mode 100644
index a45fb88..0000000
--- a/debian/patches/0005-Add-pthread-compiler-and-linker-flag.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From: Ralf Jung <post@ralfj.de>
-Date: Sat, 11 May 2013 14:24:17 +0200
-Subject: Add -pthread compiler and linker flag
-
-(based on patch in Ubuntu by Logan Rosen <logan@ubuntu.com>)
-Forwarded: http://sourceforge.net/mailarchive/forum.php?thread_name=518E3901.8050206%40ralfj.de&forum_name=osspd-users
----
- Makefile | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/Makefile b/Makefile
-index 236176e..11f2836 100644
---- a/Makefile
-+++ b/Makefile
-@@ -2,9 +2,9 @@
- # DESTDIR is completely respected
- CC := gcc
- AR := ar
--CFLAGS := -Wall $(CFLAGS) $(CPPFLAGS)
-+CFLAGS := -Wall -pthread $(CFLAGS) $(CPPFLAGS)
- XLDFLAGS := $(LDFLAGS)
--LDFLAGS := -L. -lossp $(LDFLAGS)
-+LDFLAGS := -L. -lossp -pthread $(LDFLAGS)
- prefix := /usr/local
- DESTDIR :=
- UDEVDIR := /etc/udev/rules.d
diff --git a/debian/patches/0006-fix-build-on-MIPS.patch b/debian/patches/0006-fix-build-on-MIPS.patch
deleted file mode 100644
index 9f72c3d..0000000
--- a/debian/patches/0006-fix-build-on-MIPS.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-From: Ralf Jung <post@ralfj.de>
-Date: Tue, 25 Dec 2018 18:51:01 +0100
-Subject: fix build on MIPS
-
----
- osspd.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/osspd.c b/osspd.c
-index 6b63c07..70eff98 100644
---- a/osspd.c
-+++ b/osspd.c
-@@ -22,6 +22,7 @@
- #include <stdio.h>
- #include <stdlib.h>
- #include <signal.h>
-+#include <sys/ioctl.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #include <sys/epoll.h>
diff --git a/debian/patches/0007-cross.patch b/debian/patches/0007-cross.patch
deleted file mode 100644
index 4a4b646..0000000
--- a/debian/patches/0007-cross.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From: Helmut Grohne <helmut@subdivi.de>
-Date: Tue, 21 Nov 2017 21:20:20 +0100
-Subject: fix using target-architecture pkg-config
-
----
- Makefile | 13 +++++++------
- 1 file changed, 7 insertions(+), 6 deletions(-)
-
-diff --git a/Makefile b/Makefile
-index 11f2836..bd963ca 100644
---- a/Makefile
-+++ b/Makefile
-@@ -2,6 +2,7 @@
- # DESTDIR is completely respected
- CC := gcc
- AR := ar
-+PKG_CONFIG ?= pkg-config
- CFLAGS := -Wall -pthread $(CFLAGS) $(CPPFLAGS)
- XLDFLAGS := $(LDFLAGS)
- LDFLAGS := -L. -lossp -pthread $(LDFLAGS)
-@@ -11,27 +12,27 @@ UDEVDIR := /etc/udev/rules.d
- SLAVESDIR := $(prefix)/sbin
- 
- ifeq "$(origin OSSPD_CFLAGS)" "undefined"
--OSSPD_CFLAGS := $(shell pkg-config --cflags fuse)
-+OSSPD_CFLAGS := $(shell $(PKG_CONFIG) --cflags fuse)
- endif
- 
- ifeq "$(origin OSSPD_LDFLAGS)" "undefined"
--OSSPD_LDFLAGS := $(shell pkg-config --libs fuse)
-+OSSPD_LDFLAGS := $(shell $(PKG_CONFIG) --libs fuse)
- endif
- 
- ifeq "$(origin OSSP_PADSP_CFLAGS)" "undefined"
--OSSP_PADSP_CFLAGS := $(shell pkg-config --cflags libpulse)
-+OSSP_PADSP_CFLAGS := $(shell $(PKG_CONFIG) --cflags libpulse)
- endif
- 
- ifeq "$(origin OSSP_PADSP_LDFLAGS)" "undefined"
--OSSP_PADSP_LDFLAGS := $(shell pkg-config --libs libpulse)
-+OSSP_PADSP_LDFLAGS := $(shell $(PKG_CONFIG) --libs libpulse)
- endif
- 
- ifeq "$(origin OSSP_ALSAP_CFLAGS)" "undefined"
--OSSP_ALSAP_CFLAGS := $(shell pkg-config --libs alsa)
-+OSSP_ALSAP_CFLAGS := $(shell $(PKG_CONFIG) --libs alsa)
- endif
- 
- ifeq "$(origin OSSP_ALSAP_LDFLAGS)" "undefined"
--OSSP_ALSAP_LDFLAGS := $(shell pkg-config --libs alsa)
-+OSSP_ALSAP_LDFLAGS := $(shell $(PKG_CONFIG) --libs alsa)
- endif
- 
- headers := ossp.h ossp-util.h ossp-slave.h
diff --git a/debian/patches/GIT-fix-adsp_se.patch b/debian/patches/GIT-fix-adsp_se.patch
deleted file mode 100644
index 7316f9c..0000000
--- a/debian/patches/GIT-fix-adsp_se.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 4c6161d951daa98f6463904f76b3fa2ce7216194 Mon Sep 17 00:00:00 2001
-From: Tejun Heo <tj@kernel.org>
-Date: Mon, 21 Feb 2011 11:54:06 +0100
-Subject: [PATCH] adsp_se was incorrectly created with dsp_ops.  Create it with
- adsp_ops.
-
-Reported-by: Aaron <aaron.hamid@gmail.com>
----
- osspd.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/osspd.c b/osspd.c
-index 37c9b35..df1cfc4 100644
---- a/osspd.c
-+++ b/osspd.c
-@@ -2253,7 +2253,7 @@ int main(int argc, char **argv)
- 					   param.mixer_major, param.mixer_minor,
- 					   args.argc, args.argv);
- 	if (strlen(param.adsp_name))
--		adsp_se = setup_ossp_cuse(&dsp_ops, param.adsp_name,
-+		adsp_se = setup_ossp_cuse(&adsp_ops, param.adsp_name,
- 					  param.adsp_major, param.adsp_minor,
- 					  args.argc, args.argv);
- 
diff --git a/debian/patches/GIT-fix-compiler-warnings.patch b/debian/patches/GIT-fix-compiler-warnings.patch
deleted file mode 100644
index 1424b2b..0000000
--- a/debian/patches/GIT-fix-compiler-warnings.patch
+++ /dev/null
@@ -1,251 +0,0 @@
-From 37eb730a452f0ded2ed1c174feb438e3df041581 Mon Sep 17 00:00:00 2001
-From: Miklos Szeredi <mszeredi@suse.cz>
-Date: Fri, 11 Nov 2011 14:19:32 +0100
-Subject: [PATCH] fix compiler warnings
-
----
- ossp-padsp.c |  3 ---
- osspd.c      | 75 ++++++++++++++++++++++++++++++----------------------
- 2 files changed, 44 insertions(+), 34 deletions(-)
-
-diff --git a/ossp-padsp.c b/ossp-padsp.c
-index 1871f5b..3143960 100644
---- a/ossp-padsp.c
-+++ b/ossp-padsp.c
-@@ -972,16 +972,13 @@ static void do_mmap_read(size_t bytes)
- 
- static void stream_rw_callback(pa_stream *s, size_t length, void *userdata)
- {
--	int dir;
- 	size_t size;
- 
- 	if (s == stream[PLAY]) {
--		dir = PLAY;
- 		size = pa_stream_writable_size(s);
- 		if (mmap_map[PLAY])
- 			do_mmap_write(size);
- 	} else if (s == stream[REC]) {
--		dir = REC;
- 		size = pa_stream_readable_size(s);
- 		if (mmap_map[REC])
- 			do_mmap_read(size);
-diff --git a/osspd.c b/osspd.c
-index df1cfc4..4be1ad5 100644
---- a/osspd.c
-+++ b/osspd.c
-@@ -469,15 +469,6 @@ static int ioctl_prep_uarg(fuse_req_t req, void *in, size_t in_sz, void *out,
- 		return;							\
- } while (0)
- 
--#define IOCTL_RETURN(result, outp) do {					\
--	if ((outp) != NULL)						\
--		fuse_reply_ioctl(req, result, (outp), sizeof(*(outp)));	\
--	else								\
--		fuse_reply_ioctl(req, result, NULL, 0);			\
--	return;								\
--} while (0)
--
--
- /***************************************************************************
-  * Mixer implementation
-  */
-@@ -709,7 +700,8 @@ static void mixer_simple_ioctl(fuse_req_t req, struct ossp_mixer *mixer,
- 		strncpy(info.id, id, sizeof(info.id) - 1);
- 		strncpy(info.name, name, sizeof(info.name) - 1);
- 		info.modify_counter = mixer->modify_counter;
--		IOCTL_RETURN(0, &info);
-+		fuse_reply_ioctl(req, 0, &info, sizeof(info));
-+		break;
- 	}
- 
- 	case SOUND_OLD_MIXER_INFO: {
-@@ -718,7 +710,8 @@ static void mixer_simple_ioctl(fuse_req_t req, struct ossp_mixer *mixer,
- 		PREP_UARG(NULL, &info);
- 		strncpy(info.id, id, sizeof(info.id) - 1);
- 		strncpy(info.name, name, sizeof(info.name) - 1);
--		IOCTL_RETURN(0, &info);
-+		fuse_reply_ioctl(req, 0, &info, sizeof(info));
-+		break;
- 	}
- 
- 	case OSS_GETVERSION:
-@@ -737,16 +730,16 @@ static void mixer_simple_ioctl(fuse_req_t req, struct ossp_mixer *mixer,
- 		goto puti;
- 	puti:
- 		PREP_UARG(NULL, &i);
--		IOCTL_RETURN(0, &i);
-+		fuse_reply_ioctl(req, 0, &i, sizeof(i));
-+		break;
- 
- 	case SOUND_MIXER_WRITE_RECSRC:
--		IOCTL_RETURN(0, NULL);
-+		fuse_reply_ioctl(req, 0, NULL, 0);
-+		break;
- 
- 	default:
- 		*not_minep = 1;
--		return;
- 	}
--	assert(0);
- }
- 
- static void mixer_do_ioctl(fuse_req_t req, struct ossp_mixer *mixer,
-@@ -787,7 +780,8 @@ static void mixer_do_ioctl(fuse_req_t req, struct ossp_mixer *mixer,
- 		break;
- 	default:
- 		i = 0;
--		IOCTL_RETURN(0, &i);
-+		fuse_reply_ioctl(req, 0, &i, sizeof(i));
-+		return;
- 	}
- 
- 	init_mixer_cmd(&mxcmd, mixer);
-@@ -837,7 +831,12 @@ static void mixer_do_ioctl(fuse_req_t req, struct ossp_mixer *mixer,
- 	finish_mixer_cmd(&mxcmd);
- 	free(osa);
- 
--	IOCTL_RETURN(0, out_bufsz ? &mxcmd.rvol : NULL);
-+	if (out_bufsz)
-+		fuse_reply_ioctl(req, 0, &mxcmd.rvol, sizeof(mxcmd.rvol));
-+	else
-+		fuse_reply_ioctl(req, 0, NULL, 0);
-+
-+	return;
- 
- err:
- 	fuse_reply_err(req, -rc);
-@@ -1510,7 +1509,8 @@ static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
- 	case OSS_GETVERSION:
- 		i = SNDRV_OSS_VERSION;
- 		PREP_UARG(NULL, &i);
--		IOCTL_RETURN(0, &i);
-+		fuse_reply_ioctl(req, 0, &i, sizeof(i));
-+		break;
- 
- 	case SNDCTL_DSP_GETCAPS:
- 		i = DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER |
-@@ -1519,12 +1519,14 @@ static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
- #endif
- 			DSP_CAP_MULTI;
- 		PREP_UARG(NULL, &i);
--		IOCTL_RETURN(0, &i);
-+		fuse_reply_ioctl(req, 0, &i, sizeof(i));
-+		break;
- 
- 	case SNDCTL_DSP_NONBLOCK:
- 		dsps->nonblock = 1;
- 		ret = 0;
--		IOCTL_RETURN(0, NULL);
-+		fuse_reply_ioctl(req, 0, NULL, 0);
-+		break;
- 
- 	case SNDCTL_DSP_RESET:		op = OSSP_DSP_RESET;		goto nd;
- 	case SNDCTL_DSP_SYNC:		op = OSSP_DSP_SYNC;		goto nd;
-@@ -1533,7 +1535,8 @@ static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
- 		ret = exec_simple_cmd(&dsps->os, op, NULL, NULL);
- 		if (ret)
- 			goto err;
--		IOCTL_RETURN(0, NULL);
-+		fuse_reply_ioctl(req, 0, NULL, 0);
-+		break;
- 
- 	case SOUND_PCM_READ_RATE:	op = OSSP_DSP_GET_RATE;		goto ri;
- 	case SOUND_PCM_READ_BITS:	op = OSSP_DSP_GET_FORMAT;	goto ri;
-@@ -1546,7 +1549,8 @@ static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
- 		ret = exec_simple_cmd(&dsps->os, op, NULL, &i);
- 		if (ret)
- 			goto err;
--		IOCTL_RETURN(0, &i);
-+		fuse_reply_ioctl(req, 0, &i, sizeof(i));
-+		break;
- 
- 	case SNDCTL_DSP_SPEED:		op = OSSP_DSP_SET_RATE;		goto wi;
- 	case SNDCTL_DSP_SETFMT:		op = OSSP_DSP_SET_FORMAT;	goto wi;
-@@ -1557,7 +1561,8 @@ static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
- 		ret = exec_simple_cmd(&dsps->os, op, &i, &i);
- 		if (ret)
- 			goto err;
--		IOCTL_RETURN(0, &i);
-+		fuse_reply_ioctl(req, 0, &i, sizeof(i));
-+		break;
- 
- 	case SNDCTL_DSP_STEREO:
- 		PREP_UARG(NULL, &i);
-@@ -1566,7 +1571,8 @@ static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
- 		i--;
- 		if (ret)
- 			goto err;
--		IOCTL_RETURN(0, &i);
-+		fuse_reply_ioctl(req, 0, &i, sizeof(i));
-+		break;
- 
- 	case SNDCTL_DSP_SETFRAGMENT:
- 		PREP_UARG(&i, NULL);
-@@ -1574,7 +1580,8 @@ static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
- 				      OSSP_DSP_SET_FRAGMENT, &i, NULL);
- 		if (ret)
- 			goto err;
--		IOCTL_RETURN(0, NULL);
-+		fuse_reply_ioctl(req, 0, NULL, 0);
-+		break;
- 
- 	case SNDCTL_DSP_SETTRIGGER:
- 		PREP_UARG(&i, NULL);
-@@ -1582,7 +1589,8 @@ static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
- 				      OSSP_DSP_SET_TRIGGER, &i, NULL);
- 		if (ret)
- 			goto err;
--		IOCTL_RETURN(0, NULL);
-+		fuse_reply_ioctl(req, 0, NULL, 0);
-+		break;
- 
- 	case SNDCTL_DSP_GETOSPACE:
- 	case SNDCTL_DSP_GETISPACE: {
-@@ -1603,7 +1611,8 @@ static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
- 		ret = exec_simple_cmd(&dsps->os, op, NULL, &info);
- 		if (ret)
- 			goto err;
--		IOCTL_RETURN(0, &info);
-+		fuse_reply_ioctl(req, 0, &info, sizeof(info));
-+		break;
- 	}
- 
- 	case SNDCTL_DSP_GETOPTR:
-@@ -1616,14 +1625,16 @@ static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
- 		ret = exec_simple_cmd(&dsps->os, op, NULL, &info);
- 		if (ret)
- 			goto err;
--		IOCTL_RETURN(0, &info);
-+		fuse_reply_ioctl(req, 0, &info, sizeof(info));
-+		break;
- 	}
- 
- 	case SNDCTL_DSP_GETODELAY:
- 		PREP_UARG(NULL, &i);
- 		i = 0;
- 		ret = exec_simple_cmd(&dsps->os, OSSP_DSP_GET_ODELAY, NULL, &i);
--		IOCTL_RETURN(ret, &i);	/* always copy out result, 0 on err */
-+		fuse_reply_ioctl(req, ret, &i, sizeof(i));	/* always copy out result, 0 on err */
-+		break;
- 
- 	case SOUND_PCM_WRITE_FILTER:
- 	case SOUND_PCM_READ_FILTER:
-@@ -1638,14 +1649,16 @@ static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
- 	case SNDCTL_DSP_SETSYNCRO:
- 	case SNDCTL_DSP_SETDUPLEX:
- 	case SNDCTL_DSP_PROFILE:
--		IOCTL_RETURN(0, NULL);
-+		fuse_reply_ioctl(req, 0, NULL, 0);
-+		break;
- 
- 	default:
- 		warn_os(os, "unknown ioctl 0x%x", cmd);
- 		ret = -EINVAL;
- 		goto err;
- 	}
--	assert(0);	/* control shouldn't reach here */
-+	return;
-+
- err:
- 	fuse_reply_err(req, -ret);
- }
diff --git a/debian/patches/Hack-to-work-with-modern-PulseAudio.patch b/debian/patches/Hack-to-work-with-modern-PulseAudio.patch
deleted file mode 100644
index 25996cc..0000000
--- a/debian/patches/Hack-to-work-with-modern-PulseAudio.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From: "Jan Alexander Steffens (heftig)" <jan.steffens@gmail.com>
-Date: Fri, 18 Dec 2020 23:17:36 +0000
-Subject: [PATCH] Hack to work with modern PulseAudio
-
----
- ossp-padsp.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/ossp-padsp.c b/ossp-padsp.c
-index c505b57..b4ac097 100644
---- a/ossp-padsp.c
-+++ b/ossp-padsp.c
-@@ -22,6 +22,8 @@
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <unistd.h>
-+#include <linux/limits.h>
-+#include <stdlib.h>
- 
- #include <pulse/pulseaudio.h>
- #include <sys/soundcard.h>
-@@ -1478,9 +1480,15 @@ static void action_post(void)
- int main(int argc, char **argv)
- {
- 	int rc;
-+	static char runtime_dir[PATH_MAX];
- 
- 	ossp_slave_init(argc, argv);
- 
-+	snprintf(runtime_dir, sizeof runtime_dir, "/run/user/%llu",
-+		(long long unsigned) getuid());
-+	if (access(runtime_dir, R_OK | X_OK) == 0)
-+		setenv("XDG_RUNTIME_DIR", runtime_dir, 0);
-+
- 	page_size = sysconf(_SC_PAGE_SIZE);
- 
- 	mainloop = pa_threaded_mainloop_new();
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index 03f1d68..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1,10 +0,0 @@
-0001-Fix-compilation-with-Werror-format-security.patch
-0002-honor-CPPFLAGS.patch
-0003-PA-recommends-users-not-to-be-in-the-audio-group-so-.patch
-0004-Allow-to-set-slave-installation-path-during-compilat.patch
-0005-Add-pthread-compiler-and-linker-flag.patch
-0006-fix-build-on-MIPS.patch
-0007-cross.patch
-GIT-fix-adsp_se.patch
-GIT-fix-compiler-warnings.patch
-Hack-to-work-with-modern-PulseAudio.patch
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index 2a38240..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/make -f
-
-SLAVESDIR=/usr/lib/osspd
-UDEVDIR=/lib/udev/rules.d
-
-%:
-	dh $@
-
-override_dh_auto_build:
-	dh_auto_build -- SLAVESDIR=$(SLAVESDIR) UDEVDIR=$(UDEVDIR)
-
-override_dh_auto_install:
-	dh_auto_install -- prefix=/usr SLAVESDIR=$(SLAVESDIR) UDEVDIR=$(UDEVDIR)
-
-override_dh_strip:
-	dh_strip --ddeb-migration='osspd-dbg (<< 1.3.2-7~)'
-
-override_dh_install:
-	dh_install
-	# adding kmod integration
-	install -D -m 0644 debian/osspd.kmod debian/osspd/lib/modules-load.d/osspd.conf
-
-# Disable tests, they require running the osspd
-override_dh_auto_test:
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index 919e200..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,2 +0,0 @@
-version=3
-https://sf.net/osspd/ossp-(.+)\.tar\.gz
diff --git a/ossp-alsap.c b/ossp-alsap.c
deleted file mode 100644
index 72f3bd5..0000000
--- a/ossp-alsap.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * ossp-alsap - ossp DSP slave which forwards to alsa
- *
- * Copyright (C)      2009 Maarten Lankhorst <m.b.lankhorst@gmail.com>
- *
- * This file is released under the GPLv2.
- *
- * Why an alsa plugin as well? Just to show how much
- * the alsa userspace api sucks ;-)
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <libgen.h>
-#include <limits.h>
-#include <poll.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <alsa/asoundlib.h>
-#include <sys/soundcard.h>
-
-#include "ossp-slave.h"
-
-enum {
-	AFMT_FLOAT		= 0x00004000,
-	AFMT_S32_LE		= 0x00001000,
-	AFMT_S32_BE		= 0x00002000,
-};
-
-static size_t page_size;
-
-/* alsa structures */
-static snd_pcm_t *pcm[2];
-static snd_pcm_hw_params_t *hw_params;
-static snd_pcm_sw_params_t *sw_params;
-static int block;
-
-static unsigned int byte_counter[2];
-static snd_pcm_uframes_t mmap_pos[2];
-static int stream_corked[2];
-static int stream_notify;
-
-static struct format {
-	snd_pcm_format_t format;
-	snd_pcm_sframes_t rate;
-	int channels;
-} hw_format = { SND_PCM_FORMAT_U8, 8000, 1 };
-
-#if 0
-/* future mmap stuff */
-static size_t mmap_raw_size, mmap_size;
-static int mmap_fd[2] = { -1, -1 };
-static void *mmap_map[2];
-static uint64_t mmap_idx[2];		/* mmap pointer */
-static uint64_t mmap_last_idx[2];	/* last idx for get_ptr */
-static struct ring_buf mmap_stg[2];	/* staging ring buffer */
-static size_t mmap_lead[2];		/* lead bytes */
-static int mmap_sync[2];		/* sync with backend stream */
-#endif
-
-static snd_pcm_format_t fmt_oss_to_alsa(int fmt)
-{
-	switch (fmt) {
-	case AFMT_U8:			return SND_PCM_FORMAT_U8;
-	case AFMT_A_LAW:		return SND_PCM_FORMAT_A_LAW;
-	case AFMT_MU_LAW:		return SND_PCM_FORMAT_MU_LAW;
-	case AFMT_S16_LE:		return SND_PCM_FORMAT_S16_LE;
-	case AFMT_S16_BE:		return SND_PCM_FORMAT_S16_BE;
-	case AFMT_FLOAT:		return SND_PCM_FORMAT_FLOAT;
-	case AFMT_S32_LE:		return SND_PCM_FORMAT_S32_LE;
-	case AFMT_S32_BE:		return SND_PCM_FORMAT_S32_BE;
-	default:			return SND_PCM_FORMAT_U8;
-	}
-}
-
-static int fmt_alsa_to_oss(snd_pcm_format_t fmt)
-{
-	switch (fmt) {
-	case SND_PCM_FORMAT_U8:		return AFMT_U8;
-	case SND_PCM_FORMAT_A_LAW:	return AFMT_A_LAW;
-	case SND_PCM_FORMAT_MU_LAW:	return AFMT_MU_LAW;
-	case SND_PCM_FORMAT_S16_LE:	return AFMT_S16_LE;
-	case SND_PCM_FORMAT_S16_BE:	return AFMT_S16_BE;
-	case SND_PCM_FORMAT_FLOAT:	return AFMT_FLOAT;
-	case SND_PCM_FORMAT_S32_LE:	return AFMT_S32_LE;
-	case SND_PCM_FORMAT_S32_BE:	return AFMT_S32_BE;
-	default:			return AFMT_U8;
-	}
-}
-
-static void flush_streams(int drain)
-{
-	/* FIXME: snd_pcm_drain appears to be able to deadlock,
-	 * always drop or check state? */
-	if (drain) {
-		if (pcm[PLAY])
-			snd_pcm_drain(pcm[PLAY]);
-		if (pcm[REC])
-			snd_pcm_drain(pcm[REC]);
-	} else {
-		if (pcm[PLAY])
-			snd_pcm_drop(pcm[PLAY]);
-		if (pcm[REC])
-			snd_pcm_drop(pcm[REC]);
-	}
-
-	/* XXX: Really needed? */
-#if 0
-	if (pcm[PLAY]) {
-		snd_pcm_close(pcm[PLAY]);
-		snd_pcm_open(&pcm[PLAY], "default",
-			     SND_PCM_STREAM_PLAYBACK, block);
-	}
-	if (pcm[REC]) {
-		snd_pcm_close(pcm[REC]);
-		snd_pcm_open(&pcm[REC], "default",
-			     SND_PCM_STREAM_CAPTURE, block);
-	}
-#endif
-}
-
-static void kill_streams(void)
-{
-	flush_streams(0);
-}
-
-static int trigger_streams(int play, int rec)
-{
-	int ret = 0;
-
-	if (pcm[PLAY] && play >= 0) {
-		ret = snd_pcm_sw_params_set_start_threshold(pcm[PLAY], sw_params,
-							   play ? 1 : -1);
-		if (ret >= 0)
-			snd_pcm_sw_params(pcm[PLAY], sw_params);
-	}
-	if (ret >= 0 && pcm[REC] && rec >= 0) {
-		ret = snd_pcm_sw_params_set_start_threshold(pcm[REC], sw_params,
-							    rec ? 1 : -1);
-		if (ret >= 0)
-			snd_pcm_sw_params(pcm[REC], sw_params);
-	}
-
-	return ret;
-}
-
-static ssize_t alsap_mixer(enum ossp_opcode opcode,
-			   void *carg, void *din, size_t din_sz,
-			   void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-return -EBUSY;
-}
-
-static int set_hw_params(snd_pcm_t *pcm)
-{
-	int ret;
-	unsigned rate;
-
-	ret = snd_pcm_hw_params_any(pcm, hw_params);
-	if (ret >= 0)
-		ret = snd_pcm_hw_params_set_access(pcm, hw_params,
-						   SND_PCM_ACCESS_RW_INTERLEAVED);
-	rate = hw_format.rate;
-	if (ret >= 0)
-		ret = snd_pcm_hw_params_set_rate_minmax(pcm, hw_params,
-							&rate, NULL,
-							&rate, NULL);
-	if (ret >= 0)
-		ret = snd_pcm_hw_params_set_format(pcm, hw_params, hw_format.format);
-	if (ret >= 0)
-		ret = snd_pcm_hw_params_set_channels(pcm, hw_params,
-						     hw_format.channels);
-	if (ret >= 0)
-		ret = snd_pcm_hw_params(pcm, hw_params);
-	if (ret >= 0)
-		ret = snd_pcm_sw_params_current(pcm, sw_params);
-	if (ret >= 0)
-		ret = snd_pcm_sw_params(pcm, sw_params);
-	return ret;
-}
-
-static ssize_t alsap_open(enum ossp_opcode opcode,
-			  void *carg, void *din, size_t din_sz,
-			  void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	struct ossp_dsp_open_arg *arg = carg;
-	int ret;
-	block = arg->flags & O_NONBLOCK ? SND_PCM_NONBLOCK : 0;
-	int access;
-//	block |= SND_PCM_ASYNC;
-	/* Woop dee dooo.. I love handling things in SIGIO (PAIN!!)
-	 * Probably needed for MMAP
-	 */
-
-	if (!hw_params)
-		ret = snd_pcm_hw_params_malloc(&hw_params);
-	if (ret < 0)
-		return ret;
-
-	if (!sw_params)
-		ret = snd_pcm_sw_params_malloc(&sw_params);
-	if (ret < 0)
-		return ret;
-
-	if (pcm[PLAY])
-		snd_pcm_close(pcm[PLAY]);
-	if (pcm[REC])
-		snd_pcm_close(pcm[REC]);
-	pcm[REC] = pcm[PLAY] = NULL;
-
-	access = arg->flags & O_ACCMODE;
-	if (access == O_WRONLY || access == O_RDWR) {
-		ret = snd_pcm_open(&pcm[PLAY], "default",
-				   SND_PCM_STREAM_PLAYBACK, block);
-		if (ret >= 0)
-			ret = set_hw_params(pcm[PLAY]);
-	}
-
-	if (ret >= 0 && (access == O_RDONLY || access == O_RDWR)) {
-		ret = snd_pcm_open(&pcm[REC], "default",
-				   SND_PCM_STREAM_CAPTURE, block);
-		if (ret >= 0)
-			ret = set_hw_params(pcm[REC]);
-	}
-
-	if (ret < 0) {
-		if (pcm[PLAY])
-			snd_pcm_close(pcm[PLAY]);
-		if (pcm[REC])
-			snd_pcm_close(pcm[REC]);
-		pcm[REC] = pcm[PLAY] = NULL;
-		return ret;
-	}
-	return 0;
-}
-
-static ssize_t alsap_write(enum ossp_opcode opcode,
-			   void *carg, void *din, size_t din_sz,
-			   void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-//	struct ossp_dsp_rw_arg *arg = carg;
-	int ret, insize;
-
-	insize = snd_pcm_bytes_to_frames(pcm[PLAY], din_sz);
-
-	if (snd_pcm_state(pcm[PLAY]) == SND_PCM_STATE_SETUP)
-		snd_pcm_prepare(pcm[PLAY]);
-
-//	snd_pcm_start(pcm[PLAY]);
-	ret = snd_pcm_writei(pcm[PLAY], din, insize);
-	if (ret < 0)
-		ret = snd_pcm_recover(pcm[PLAY], ret, 1);
-
-	if (ret >= 0)
-		return snd_pcm_frames_to_bytes(pcm[PLAY], ret);
-	else
-		return ret;
-}
-
-static ssize_t alsap_read(enum ossp_opcode opcode,
-			  void *carg, void *din, size_t din_sz,
-			  void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-//	struct ossp_dsp_rw_arg *arg = carg;
-	int ret, outsize;
-
-	outsize = snd_pcm_bytes_to_frames(pcm[REC], *dout_szp);
-
-	if (snd_pcm_state(pcm[REC]) == SND_PCM_STATE_SETUP)
-		snd_pcm_prepare(pcm[REC]);
-
-	ret = snd_pcm_readi(pcm[REC], dout, outsize);
-	if (ret < 0)
-		ret = snd_pcm_recover(pcm[REC], ret, 1);
-	if (ret >= 0)
-		*dout_szp = ret = snd_pcm_frames_to_bytes(pcm[REC], ret);
-	else
-		*dout_szp = 0;
-
-	return ret;
-}
-
-static ssize_t alsap_poll(enum ossp_opcode opcode,
-			  void *carg, void *din, size_t din_sz,
-			  void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	unsigned revents = 0;
-
-	stream_notify |= *(int *)carg;
-
-	if (pcm[PLAY])
-		revents |= POLLOUT;
-	if (pcm[REC])
-		revents |= POLLIN;
-
-	*(unsigned *)rarg = revents;
-	return 0;
-}
-
-
-static ssize_t alsap_flush(enum ossp_opcode opcode,
-			   void *carg, void *din, size_t din_sz,
-			   void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	flush_streams(opcode == OSSP_DSP_SYNC);
-	return 0;
-}
-
-static ssize_t alsap_post(enum ossp_opcode opcode,
-			  void *carg, void *din, size_t din_sz,
-			  void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	int ret;
-
-	ret = trigger_streams(1, 1);
-	if (ret >= 0 && pcm[PLAY])
-		ret = snd_pcm_start(pcm[PLAY]);
-	if (pcm[REC])
-		ret = snd_pcm_start(pcm[REC]);
-	return ret;
-}
-
-static ssize_t alsap_get_param(enum ossp_opcode opcode,
-			       void *carg, void *din, size_t din_sz,
-			       void *rarg, void *dout, size_t *dout_szp,
-			       int tfd)
-{
-	int v = 0;
-
-	switch (opcode) {
-	case OSSP_DSP_GET_RATE:
-		return hw_format.rate;
-
-	case OSSP_DSP_GET_CHANNELS:
-		return hw_format.channels;
-
-	case OSSP_DSP_GET_FORMAT: {
-		v = fmt_alsa_to_oss(hw_format.format);
-		break;
-	}
-
-	case OSSP_DSP_GET_BLKSIZE: {
-		snd_pcm_uframes_t psize;
-		snd_pcm_hw_params_get_period_size(hw_params, &psize, NULL);
-		v = psize;
-		break;
-	}
-
-	case OSSP_DSP_GET_FORMATS:
-		v = AFMT_U8 | AFMT_A_LAW | AFMT_MU_LAW | AFMT_S16_LE |
-			AFMT_S16_BE | AFMT_FLOAT | AFMT_S32_LE | AFMT_S32_BE;
-		break;
-
-	case OSSP_DSP_GET_TRIGGER:
-		if (!stream_corked[PLAY])
-			v |= PCM_ENABLE_OUTPUT;
-		if (!stream_corked[REC])
-			v |= PCM_ENABLE_INPUT;
-		break;
-
-	default:
-		assert(0);
-	}
-
-	*(int *)rarg = v;
-
-	return 0;
-}
-
-static ssize_t alsap_set_param(enum ossp_opcode opcode,
-			       void *carg, void *din, size_t din_sz,
-			       void *rarg, void *dout, size_t *dout_szp,
-			       int tfd)
-{
-	int v = *(int *)carg;
-	int ret = 0;
-
-	/* kill the streams before changing parameters */
-	kill_streams();
-
-	switch (opcode) {
-	case OSSP_DSP_SET_RATE: {
-		hw_format.rate = v;
-		break;
-	}
-
-	case OSSP_DSP_SET_CHANNELS: {
-		hw_format.channels = v;
-		break;
-	}
-
-	case OSSP_DSP_SET_FORMAT: {
-		snd_pcm_format_t format = fmt_oss_to_alsa(v);
-		hw_format.format = format;
-		break;
-	}
-
-	case OSSP_DSP_SET_SUBDIVISION:
-		if (!v)
-			v = 1;
-#if 0
-		if (!v) {
-			v = user_subdivision ?: 1;
-			break;
-		}
-		user_frag_size = 0;
-		user_subdivision = v;
-		break;
-
-	case OSSP_DSP_SET_FRAGMENT:
-		user_subdivision = 0;
-		user_frag_size = 1 << (v & 0xffff);
-		user_max_frags = (v >> 16) & 0xffff;
-		if (user_frag_size < 4)
-			user_frag_size = 4;
-		if (user_max_frags < 2)
-			user_max_frags = 2;
-#else
-	case OSSP_DSP_SET_FRAGMENT:
-#endif
-		break;
-	default:
-		assert(0);
-	}
-
-	if (pcm[PLAY])
-		ret = set_hw_params(pcm[PLAY]);
-	if (ret >= 0 && pcm[REC])
-		ret = set_hw_params(pcm[REC]);
-
-	if (rarg)
-		*(int *)rarg = v;
-	return 0;
-}
-
-static ssize_t alsap_set_trigger(enum ossp_opcode opcode,
-				 void *carg, void *din, size_t din_sz,
-				 void *rarg, void *dout, size_t *dout_szp,
-				 int fd)
-{
-	int enable = *(int *)carg;
-
-	stream_corked[PLAY] = !!(enable & PCM_ENABLE_OUTPUT);
-	stream_corked[REC] = !!(enable & PCM_ENABLE_INPUT);
-
-	return trigger_streams(enable & PCM_ENABLE_OUTPUT,
-			       enable & PCM_ENABLE_INPUT);
-}
-
-static ssize_t alsap_get_space(enum ossp_opcode opcode,
-			       void *carg, void *din, size_t din_sz,
-			       void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	int dir = (opcode == OSSP_DSP_GET_OSPACE) ? PLAY : REC;
-	int underrun = 0;
-	struct audio_buf_info info = { };
-	unsigned long bufsize;
-	snd_pcm_uframes_t avail, fragsize;
-	snd_pcm_state_t state;
-
-	if (!pcm[dir])
-		return -EINVAL;
-
-	state = snd_pcm_state(pcm[dir]);
-	if (state == SND_PCM_STATE_XRUN) {
-		snd_pcm_recover(pcm[dir], -EPIPE, 0);
-		underrun = 1;
-	} else if (state == SND_PCM_STATE_SUSPENDED) {
-		snd_pcm_recover(pcm[dir], -ESTRPIPE, 0);
-		underrun = 1;
-	}
-
-	snd_pcm_hw_params_current(pcm[dir], hw_params);
-	snd_pcm_hw_params_get_period_size(hw_params, &fragsize, NULL);
-	snd_pcm_hw_params_get_buffer_size(hw_params, &bufsize);
-	info.fragsize = snd_pcm_frames_to_bytes(pcm[dir], fragsize);
-	info.fragstotal = bufsize / fragsize;
-	if (!underrun) {
-		avail = snd_pcm_avail_update(pcm[dir]);
-		info.fragments = avail / fragsize;
-	} else
-		info.fragments = info.fragstotal;
-
-	info.bytes = info.fragsize * info.fragments;
-
-	*(struct audio_buf_info *)rarg = info;
-	return 0;
-}
-
-static ssize_t alsap_get_ptr(enum ossp_opcode opcode,
-			     void *carg, void *din, size_t din_sz,
-			     void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	int dir = (opcode == OSSP_DSP_GET_OPTR) ? PLAY : REC;
-	struct count_info info = { };
-
-	if (!pcm[dir])
-		return -EIO;
-
-	snd_pcm_hw_params_current(pcm[dir], hw_params);
-	info.bytes = byte_counter[dir];
-	snd_pcm_hw_params_get_periods(hw_params, (unsigned int *)&info.blocks, NULL);
-	info.ptr = mmap_pos[dir];
-
-	*(struct count_info *)rarg = info;
-	return 0;
-}
-
-static ssize_t alsap_get_odelay(enum ossp_opcode opcode,
-				void *carg, void *din, size_t din_sz,
-				void *rarg, void *dout, size_t *dout_szp,
-				int fd)
-{
-	snd_pcm_sframes_t delay;
-
-	if (!pcm[PLAY])
-		return -EIO;
-
-	if (snd_pcm_delay(pcm[PLAY], &delay) < 0)
-		return -EIO;
-
-	*(int *)rarg = snd_pcm_frames_to_bytes(pcm[PLAY], delay);
-	return 0;
-}
-
-static ossp_action_fn_t action_fn_tbl[OSSP_NR_OPCODES] = {
-	[OSSP_MIXER]		= alsap_mixer,
-	[OSSP_DSP_OPEN]		= alsap_open,
-	[OSSP_DSP_READ]		= alsap_read,
-	[OSSP_DSP_WRITE]	= alsap_write,
-	[OSSP_DSP_POLL]		= alsap_poll,
-#if 0
-	[OSSP_DSP_MMAP]		= alsap_mmap,
-	[OSSP_DSP_MUNMAP]	= alsap_munmap,
-#endif
-	[OSSP_DSP_RESET]	= alsap_flush,
-	[OSSP_DSP_SYNC]		= alsap_flush,
-	[OSSP_DSP_POST]		= alsap_post,
-	[OSSP_DSP_GET_RATE]	= alsap_get_param,
-	[OSSP_DSP_GET_CHANNELS]	= alsap_get_param,
-	[OSSP_DSP_GET_FORMAT]	= alsap_get_param,
-	[OSSP_DSP_GET_BLKSIZE]	= alsap_get_param,
-	[OSSP_DSP_GET_FORMATS]	= alsap_get_param,
-	[OSSP_DSP_SET_RATE]	= alsap_set_param,
-	[OSSP_DSP_SET_CHANNELS]	= alsap_set_param,
-	[OSSP_DSP_SET_FORMAT]	= alsap_set_param,
-	[OSSP_DSP_SET_SUBDIVISION] = alsap_set_param,
-	[OSSP_DSP_SET_FRAGMENT]	= alsap_set_param,
-	[OSSP_DSP_GET_TRIGGER]	= alsap_get_param,
-	[OSSP_DSP_SET_TRIGGER]	= alsap_set_trigger,
-	[OSSP_DSP_GET_OSPACE]	= alsap_get_space,
-	[OSSP_DSP_GET_ISPACE]	= alsap_get_space,
-	[OSSP_DSP_GET_OPTR]	= alsap_get_ptr,
-	[OSSP_DSP_GET_IPTR]	= alsap_get_ptr,
-	[OSSP_DSP_GET_ODELAY]	= alsap_get_odelay,
-};
-
-static int action_pre(void)
-{
-	return 0;
-}
-
-static void action_post(void)
-{
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	ossp_slave_init(argc, argv);
-
-	page_size = sysconf(_SC_PAGE_SIZE);
-
-	/* Okay, now we're open for business */
-	rc = 0;
-	do {
-		rc = ossp_slave_process_command(ossp_cmd_fd, action_fn_tbl,
-						action_pre, action_post);
-	} while (rc > 0);
-
-	return rc ? 1 : 0;
-}
diff --git a/ossp-padsp.c b/ossp-padsp.c
deleted file mode 100644
index 1871f5b..0000000
--- a/ossp-padsp.c
+++ /dev/null
@@ -1,1524 +0,0 @@
-/*
- * ossp-padsp - ossp DSP slave which forwards to pulseaduio
- *
- * Copyright (C) 2008-2010  SUSE Linux Products GmbH
- * Copyright (C) 2008-2010  Tejun Heo <tj@kernel.org>
- *
- * This file is released under the GPLv2.
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <libgen.h>
-#include <limits.h>
-#include <poll.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <pulse/pulseaudio.h>
-#include <sys/soundcard.h>
-
-#include "ossp-slave.h"
-
-enum {
-	AFMT_FLOAT		= 0x00004000,
-	AFMT_S32_LE		= 0x00001000,
-	AFMT_S32_BE		= 0x00002000,
-};
-
-/* everything is in millisecs */
-struct stream_params {
-	size_t		min_process;
-	size_t		min_latency;
-	size_t		dfl_process;
-	size_t		dfl_latency;
-	size_t		mmap_process;
-	size_t		mmap_latency;
-	size_t		mmap_lead;
-	size_t		mmap_staging;
-};
-
-/* TODO: make this configurable */
-static struct stream_params stream_params[] = {
-	[ PLAY ] = { .min_process = 25,		.min_latency = 100,
-		     .dfl_process = 50,		.dfl_latency = 200,
-		     .mmap_process = 25,	.mmap_latency = 50,
-		     .mmap_lead = 25,		.mmap_staging = 100 },
-	[ REC ]	 = { .min_process = 25,		.min_latency = 200,
-		     .dfl_process = 50,		.dfl_latency = 400,
-		     .mmap_process = 25,	.mmap_latency = 50,
-		     .mmap_lead = 25,		.mmap_staging = 1000 },
-};
-
-static size_t page_size;
-static pa_context *context;
-static pa_threaded_mainloop *mainloop;
-static pa_mainloop_api *mainloop_api;
-static char stream_name[128];
-static int stream_enabled[2];
-static int stream_corked[2];
-static int stream_waiting;
-static int stream_notify;
-static pa_channel_map channel_map_stor;
-static pa_channel_map *channel_map;
-static pa_stream *stream[2];
-static pa_usec_t stream_ptr_timestamp[2];
-static struct ring_buf rec_buf;
-static int stored_oss_vol[2][2] = { { -1, -1 }, { -1, -1 } };
-static int fail_code;
-
-static pa_sample_spec sample_spec = {
-	.format = PA_SAMPLE_U8,
-	.rate = 8000,
-	.channels = 1,
-};
-static size_t sample_bps = 8000;
-static size_t frame_size = 1;
-
-/* user visible stream parameters */
-static size_t user_frag_size;
-static size_t user_subdivision;	/* alternative way to determine frag_size */
-static size_t user_max_frags;	/* maximum number of fragments */
-static size_t user_max_length;
-
-/* actual stream parameters */
-static size_t frag_size;
-static size_t target_length;
-static size_t max_length;
-static size_t prebuf_size;
-
-/* mmap stuff */
-static size_t mmap_raw_size, mmap_size;
-static void *mmap_map[2];
-static uint64_t mmap_idx[2];		/* mmap pointer */
-static uint64_t mmap_last_idx[2];	/* last idx for get_ptr */
-static struct ring_buf mmap_stg[2];	/* staging ring buffer */
-static size_t mmap_lead[2];		/* lead bytes */
-static int mmap_sync[2];		/* sync with backend stream */
-
-static const char *dir_str[] = {
-	[PLAY]		= "PLAY",
-	[REC]		= "REC",
-};
-
-static void stream_rw_callback(pa_stream *s, size_t length, void *userdata);
-
-#define __pa_err		pa_strerror(pa_context_errno(context))
-#define dbg1_pa(fmt, args...)	dbg1(fmt" (%s)" , ##args, __pa_err)
-#define dbg0_pa(fmt, args...)	dbg0(fmt" (%s)" , ##args, __pa_err)
-#define info_pa(fmt, args...)	info(fmt" (%s)" , ##args, __pa_err)
-#define warn_pa(fmt, args...)	warn(fmt" (%s)" , ##args, __pa_err)
-#define err_pa(fmt, args...)	err(fmt" (%s)" , ##args, __pa_err)
-
-#define round_down(v, t)	((v) / (t) * (t))
-#define round_up(v, t)		(((v) + (t) - 1) / (t) * (t))
-#define is_power2(v)		!((v) & ((v) - 1))
-
-static int do_mixer(int dir, int *vol);
-
-static int padsp_done(void)
-{
-	fail_code = -EIO;
-	mainloop_api->quit(mainloop_api, 1);
-	return fail_code;
-}
-
-static int fmt_oss_to_pa(int fmt)
-{
-	switch (fmt) {
-	case AFMT_U8:			return PA_SAMPLE_U8;
-	case AFMT_A_LAW:		return PA_SAMPLE_ALAW;
-	case AFMT_MU_LAW:		return PA_SAMPLE_ULAW;
-	case AFMT_S16_LE:		return PA_SAMPLE_S16LE;
-	case AFMT_S16_BE:		return PA_SAMPLE_S16BE;
-	case AFMT_FLOAT:		return PA_SAMPLE_FLOAT32NE;
-	case AFMT_S32_LE:		return PA_SAMPLE_S32LE;
-	case AFMT_S32_BE:		return PA_SAMPLE_S32BE;
-	default:			return PA_SAMPLE_U8;
-	}
-}
-
-static int fmt_pa_to_oss(int fmt)
-{
-	switch (fmt) {
-	case PA_SAMPLE_U8:		return AFMT_U8;
-	case PA_SAMPLE_ALAW:		return AFMT_A_LAW;
-	case PA_SAMPLE_ULAW:		return AFMT_MU_LAW;
-	case PA_SAMPLE_S16LE:		return AFMT_S16_LE;
-	case PA_SAMPLE_S16BE:		return AFMT_S16_BE;
-	case PA_SAMPLE_FLOAT32NE:	return AFMT_FLOAT;
-	case PA_SAMPLE_S32LE:		return AFMT_S32_LE;
-	case PA_SAMPLE_S32BE:		return AFMT_S32_BE;
-	default:			return AFMT_U8;
-	}
-}
-
-#define EXEC_OP(op, args...)	do {					\
-	pa_operation *_o;						\
-	_o = op(args);							\
-	if (_o) {							\
-		while (pa_operation_get_state(_o) != PA_OPERATION_DONE)	\
-			pa_threaded_mainloop_wait(mainloop);		\
-		pa_operation_unref(_o);					\
-	} } while (0)
-
-static void context_op_callback(pa_context *s, int success, void *userdata)
-{
-	*(int *)userdata = success;
-	pa_threaded_mainloop_signal(mainloop, 0);
-}
-
-static void stream_op_callback(pa_stream *s, int success, void *userdata)
-{
-	*(int *)userdata = success;
-	pa_threaded_mainloop_signal(mainloop, 0);
-}
-
-#define EXEC_CONTEXT_OP(op, args...) ({					\
-	int _success;							\
-	EXEC_OP(op , ##args, context_op_callback, &_success);		\
-	if (!_success)							\
-		warn_pa("%s() failed", #op);				\
-	_success ? 0 : -EIO; })
-
-#define EXEC_STREAM_OP(op, args...) ({					\
-	int _success;							\
-	EXEC_OP(op , ##args, stream_op_callback, &_success);		\
-	if (!_success)							\
-		warn_pa("%s() failed", #op);				\
-	_success ? 0 : -EIO; })
-
-static int mmapped(void)
-{
-	return mmap_map[PLAY] || mmap_map[REC];
-}
-
-static uint64_t get_mmap_idx(int dir)
-{
-	uint64_t idx;
-	pa_usec_t time;
-
-	if (!stream[dir])
-		return mmap_idx[dir];
-
-	if (pa_stream_get_time(stream[dir], &time) < 0) {
-		dbg1_pa("pa_stream_get_time() failed");
-		return mmap_idx[dir];
-	}
-
-	/* calculate the current index from time elapsed */
-	idx = ((uint64_t)time * sample_bps / 1000000);
-	/* round down to the nearest frame boundary */
-	idx = idx / frame_size * frame_size;
-
-	return idx;
-}
-
-static void flush_streams(int drain)
-{
-	int i;
-
-	if (!(stream[PLAY] || stream[REC]))
-		return;
-
-	dbg0("FLUSH drain=%d", drain);
-
-	/* mmapped streams run forever, can't drain */
-	if (drain && !mmapped() && stream[PLAY])
-		EXEC_STREAM_OP(pa_stream_drain, stream[PLAY]);
-
-	for (i = 0; i < 2; i++)
-		if (stream[i])
-			EXEC_STREAM_OP(pa_stream_flush, stream[i]);
-
-	ring_consume(&rec_buf, ring_bytes(&rec_buf));
-}
-
-static void kill_streams(void)
-{
-	int dir;
-
-	if (!(stream[PLAY] || stream[REC]))
-		return;
-
-	flush_streams(1);
-
-	dbg0("KILL");
-
-	for (dir = 0; dir < 2; dir++) {
-		if (!stream[dir])
-			continue;
-		pa_stream_disconnect(stream[dir]);
-		pa_stream_unref(stream[dir]);
-		stream[dir] = NULL;
-		stream_ptr_timestamp[dir] = 0;
-
-		ring_consume(&mmap_stg[dir], ring_bytes(&mmap_stg[dir]));
-		ring_resize(&mmap_stg[dir], 0);
-	}
-}
-
-static int trigger_streams(int play, int rec)
-{
-	int ret = 0, dir, rc;
-
-	if (play >= 0)
-		stream_corked[PLAY] = !play;
-	if (rec >= 0)
-		stream_corked[REC] = !rec;
-
-	for (dir = 0; dir < 2; dir++) {
-		if (!stream[dir])
-			continue;
-
-		rc = EXEC_STREAM_OP(pa_stream_cork, stream[dir],
-				    stream_corked[dir]);
-		if (!rc && dir == PLAY && !mmap_map[dir] && !stream_corked[dir])
-			rc = EXEC_STREAM_OP(pa_stream_trigger, stream[dir]);
-		if (!ret)
-			ret = rc;
-	}
-
-	return ret;
-}
-
-static void stream_state_callback(pa_stream *s, void *userdata)
-{
-	pa_threaded_mainloop_signal(mainloop, 0);
-}
-
-static void stream_underflow_callback(pa_stream *s, void *userdata)
-{
-	int dir = (s == stream[PLAY]) ? PLAY : REC;
-
-	dbg0("%s stream underrun", dir_str[dir]);
-}
-
-static void stream_overflow_callback(pa_stream *s, void *userdata)
-{
-	int dir = (s == stream[PLAY]) ? PLAY : REC;
-
-	dbg0("%s stream overrun", dir_str[dir]);
-}
-
-static size_t duration_to_bytes(size_t dur)
-{
-	return round_up(dur * sample_bps / 1000, frame_size);
-}
-
-static int prepare_streams(void)
-{
-	const struct stream_params *sp;
-	size_t min_frag_size, min_target_length, tmp;
-	int dir, rc;
-
-	/* nothing to do? */
-	if ((!stream_enabled[PLAY] || stream[PLAY]) &&
-	    (!stream_enabled[REC] || stream[REC]))
-		return 0;
-
-	/* determine sample parameters */
-	sample_bps = pa_bytes_per_second(&sample_spec);
-	frame_size = pa_frame_size(&sample_spec);
-
-	sp = &stream_params[PLAY];
-	if (stream_enabled[REC])
-		sp = &stream_params[REC];
-
-	min_frag_size = duration_to_bytes(sp->min_process);
-	min_target_length = duration_to_bytes(sp->min_latency);
-
-	/* determine frag_size */
-	if (user_frag_size % frame_size) {
-		warn("requested frag_size (%zu) isn't multiple of frame (%zu)",
-		     user_frag_size, frame_size);
-		user_frag_size = round_up(user_frag_size, frame_size);
-	}
-
-	if (user_subdivision)
-		user_frag_size = round_up(sample_bps / user_subdivision,
-					  frame_size);
-
-	if (user_frag_size) {
-		frag_size = user_frag_size;
-		if (frag_size < min_frag_size) {
-			dbg0("requested frag_size (%zu) is smaller than "
-			     "minimum (%zu)", frag_size, min_frag_size);
-			frag_size = min_frag_size;
-		}
-	} else {
-		tmp = round_up(sp->dfl_process * sample_bps / 1000, frame_size);
-		frag_size = tmp;
-		/* if frame_size is power of two, make frag_size so too */
-		if (is_power2(frame_size)) {
-			frag_size = frame_size;
-			while (frag_size < tmp)
-				frag_size <<= 1;
-		}
-		user_frag_size = frag_size;
-	}
-
-	/* determine target and max length */
-	if (user_max_frags) {
-		target_length = user_max_frags * user_frag_size;
-		if (target_length < min_target_length) {
-			dbg0("requested target_length (%zu) is smaller than "
-			     "minimum (%zu)", target_length, min_target_length);
-			target_length = min_target_length;
-		}
-	} else {
-		tmp = round_up(sp->dfl_latency * sample_bps / 1000, frag_size);
-		target_length = tmp;
-		/* if frag_size is power of two, make target_length so
-		 * too and align it to page_size.
-		 */
-		if (is_power2(frag_size)) {
-			target_length = frag_size;
-			while (target_length < max(tmp, page_size))
-				target_length <<= 1;
-		}
-		user_max_frags = target_length / frag_size;
-	}
-
-	user_max_length = user_frag_size * user_max_frags;
-	max_length = target_length + 2 * frag_size;
-
-	/* If mmapped, create backend stream with fixed parameters to
-	 * create illusion of hardware buffer with acceptable latency.
-	 */
-	if (mmapped()) {
-		/* set parameters for backend streams */
-		frag_size = duration_to_bytes(sp->mmap_process);
-		target_length = duration_to_bytes(sp->mmap_latency);
-		max_length = target_length + frag_size;
-		prebuf_size = 0;
-
-		mmap_size = round_down(mmap_raw_size, frame_size);
-		if (mmap_size != mmap_raw_size)
-			warn("mmap_raw_size (%zu) unaligned to frame_size "
-			     "(%zu), mmap_size adjusted to %zu",
-			     mmap_raw_size, frame_size, mmap_size);
-	} else {
-		prebuf_size = min(user_frag_size * 2, user_max_length / 2);
-		prebuf_size = round_down(prebuf_size, frame_size);
-	}
-
-	for (dir = 0; dir < 2; dir++) {
-		pa_buffer_attr new_ba = { };
-		char buf[128];
-		pa_stream *s;
-		pa_stream_flags_t flags;
-		int vol[2];
-		size_t size;
-
-		if (!stream_enabled[dir] || stream[dir])
-			continue;
-
-		dbg0("CREATE %s %s fsz=%zu:%zu", dir_str[dir],
-		     pa_sample_spec_snprint(buf, sizeof(buf), &sample_spec),
-		     frag_size, frag_size * 1000 / sample_bps);
-		dbg0("  tlen=%zu:%zu max=%zu:%zu pre=%zu:%zu",
-		     target_length, target_length * 1000 / sample_bps,
-		     max_length, max_length * 1000 / sample_bps,
-		     prebuf_size, prebuf_size * 1000 / sample_bps);
-		dbg0("  u_sd=%zu u_fsz=%zu:%zu u_maxf=%zu",
-		     user_subdivision, user_frag_size,
-		     user_frag_size * 1000 / sample_bps, user_max_frags);
-
-		channel_map = pa_channel_map_init_auto(&channel_map_stor,
-						       sample_spec.channels,
-						       PA_CHANNEL_MAP_OSS);
-
-		s = pa_stream_new(context, stream_name, &sample_spec,
-				  channel_map);
-		if (!s) {
-			err_pa("can't create streams");
-			goto fail;
-		}
-		stream[dir] = s;
-
-		pa_stream_set_state_callback(s, stream_state_callback, NULL);
-		if (dir == PLAY) {
-			pa_stream_set_write_callback(s,
-					stream_rw_callback, NULL);
-			pa_stream_set_underflow_callback(s,
-					stream_underflow_callback, NULL);
-		} else {
-			pa_stream_set_read_callback(s,
-					stream_rw_callback, NULL);
-			pa_stream_set_overflow_callback(s,
-					stream_overflow_callback, NULL);
-		}
-
-		flags = PA_STREAM_AUTO_TIMING_UPDATE |
-			PA_STREAM_INTERPOLATE_TIMING;
-		if (stream_corked[dir])
-			flags |= PA_STREAM_START_CORKED;
-
-		new_ba.maxlength = max_length;
-		new_ba.tlength = target_length;
-		new_ba.prebuf = prebuf_size;
-		new_ba.minreq = frag_size;
-		new_ba.fragsize = frag_size;
-
-		if (dir == PLAY) {
-			if (pa_stream_connect_playback(s, NULL, &new_ba, flags,
-						       NULL, NULL)) {
-				err_pa("failed to connect playback stream");
-				goto fail;
-			}
-		} else {
-			if (pa_stream_connect_record(s, NULL, &new_ba, flags)) {
-				err_pa("failed to connect record stream");
-				goto fail;
-			}
-		}
-
-		while (pa_stream_get_state(s) == PA_STREAM_CREATING)
-			pa_threaded_mainloop_wait(mainloop);
-		if (pa_stream_get_state(s) != PA_STREAM_READY) {
-			err_pa("failed to connect stream (state=%d)",
-			       pa_stream_get_state(s));
-			goto fail;
-		}
-
-		/* apply stored OSS volume */
-		memcpy(vol, stored_oss_vol[dir], sizeof(vol));
-		if (do_mixer(dir, vol))
-			warn_pa("initial volume control failed");
-
-		/* stream is ready setup mmap stuff */
-		if (!mmap_map[dir])
-			continue;
-
-		/* prep mmap staging buffer */
-		size = round_up(sp->mmap_staging * sample_bps / 1000,
-				frag_size);
-		rc = ring_resize(&mmap_stg[dir], size);
-		if (rc)
-			return rc;
-
-		mmap_idx[dir] = mmap_last_idx[dir] = get_mmap_idx(dir);
-		mmap_lead[dir] = round_up(sp->mmap_lead * sample_bps / 1000,
-					  frame_size);
-		mmap_sync[dir] = 1;
-
-		/* apply the current trigger settings */
-		trigger_streams(-1, -1);
-	}
-
-	return 0;
- fail:
-	return padsp_done();
-}
-
-struct volume_ret {
-	int			success;
-	pa_cvolume		*cv;
-};
-
-static void play_volume_callback(pa_context *c, const pa_sink_input_info *i,
-				 int eol, void *userdata)
-{
-	struct volume_ret *vr = userdata;
-
-	if (i) {
-		*vr->cv = i->volume;
-		vr->success = 1;
-	}
-	pa_threaded_mainloop_signal(mainloop, 0);
-}
-
-static void rec_volume_callback(pa_context *c, const pa_source_info *i,
-				int eol, void *userdata)
-{
-	struct volume_ret *vr = userdata;
-
-	if (i) {
-		*vr->cv = i->volume;
-		vr->success = 1;
-	}
-	pa_threaded_mainloop_signal(mainloop, 0);
-}
-
-static int get_volume(int dir, pa_cvolume *cv)
-{
-	struct volume_ret vr = { .cv = cv };
-	uint32_t idx;
-
-	if (dir == PLAY) {
-		idx = pa_stream_get_index(stream[PLAY]);
-		EXEC_OP(pa_context_get_sink_input_info,
-			context, idx, play_volume_callback, &vr);
-	} else {
-		idx = pa_stream_get_device_index(stream[REC]);
-		EXEC_OP(pa_context_get_source_info_by_index,
-			context, idx, rec_volume_callback, &vr);
-	}
-	if (!vr.success) {
-		warn_pa("failed to get %s volume", dir_str[dir]);
-		return -EIO;
-	}
-	return 0;
-}
-
-static int set_volume(int dir, pa_cvolume *cv)
-{
-	uint32_t idx;
-	int rc;
-
-	if (dir == PLAY) {
-		idx = pa_stream_get_index(stream[PLAY]);
-		rc = EXEC_CONTEXT_OP(pa_context_set_sink_input_volume,
-				     context, idx, cv);
-	} else {
-		idx = pa_stream_get_device_index(stream[REC]);
-		rc = EXEC_CONTEXT_OP(pa_context_set_source_volume_by_index,
-				     context, idx, cv);
-	}
-	return rc;
-}
-
-static int chan_left_right(int ch)
-{
-	if (!channel_map || channel_map->channels <= ch) {
-		switch (ch) {
-		case 0:
-			return LEFT;
-		case 1:
-			return RIGHT;
-		default:
-			return -1;
-		}
-	}
-
-	switch (channel_map->map[ch]) {
-	/*case PA_CHANNEL_POSITION_LEFT:*/	/* same as FRONT_LEFT */
-	case PA_CHANNEL_POSITION_FRONT_LEFT:
-	case PA_CHANNEL_POSITION_REAR_LEFT:
-	case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
-	case PA_CHANNEL_POSITION_SIDE_LEFT:
-	case PA_CHANNEL_POSITION_TOP_FRONT_LEFT:
-	case PA_CHANNEL_POSITION_TOP_REAR_LEFT:
-		return LEFT;
-	/*case PA_CHANNEL_POSITION_RIGHT:*/	/* same as FRONT_RIGHT */
-	case PA_CHANNEL_POSITION_FRONT_RIGHT:
-	case PA_CHANNEL_POSITION_REAR_RIGHT:
-	case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
-	case PA_CHANNEL_POSITION_SIDE_RIGHT:
-	case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT:
-	case PA_CHANNEL_POSITION_TOP_REAR_RIGHT:
-		return RIGHT;
-	default:
-		return -1;
-	}
-}
-
-static int do_mixer(int dir, int *vol)
-{
-	pa_cvolume cv;
-	unsigned lv, rv;
-	int i, rc;
-
-	if (vol[0] >= 0) {
-		int avg;
-
-		stored_oss_vol[dir][LEFT] = vol[LEFT];
-		stored_oss_vol[dir][RIGHT] = vol[RIGHT];
-		vol[LEFT] = vol[LEFT] * PA_VOLUME_NORM / 100;
-		vol[RIGHT] = vol[RIGHT] * PA_VOLUME_NORM / 100;
-		avg = (vol[LEFT] + vol[RIGHT]) / 2;
-
-		pa_cvolume_mute(&cv, sample_spec.channels);
-
-		for (i = 0; i < cv.channels; i++)
-			switch (chan_left_right(i)) {
-			case LEFT:	cv.values[i] = vol[LEFT];	break;
-			case RIGHT:	cv.values[i] = vol[RIGHT];	break;
-			default:	cv.values[i] = avg;		break;
-			}
-
-		rc = set_volume(dir, &cv);
-		if (rc)
-			return rc;
-	}
-
-	rc = get_volume(dir, &cv);
-	if (rc)
-		return rc;
-
-	if (cv.channels == 1)
-		lv = rv = pa_cvolume_avg(&cv);
-	else {
-		unsigned lcnt = 0, rcnt = 0;
-
-		for (i = 0, lv = 0, rv = 0; i < cv.channels; i++)
-			switch (chan_left_right(i)) {
-			case LEFT:	lv += cv.values[i];	lcnt++;	break;
-			case RIGHT:	rv += cv.values[i];	rcnt++;	break;
-			}
-
-		if (lcnt)
-			lv /= lcnt;
-		if (rcnt)
-			rv /= rcnt;
-	}
-
-	vol[LEFT] = lv * 100 / PA_VOLUME_NORM;
-	vol[RIGHT] = rv * 100 / PA_VOLUME_NORM;
-
-	return 0;
-}
-
-static ssize_t padsp_mixer(enum ossp_opcode opcode,
-			   void *carg, void *din, size_t din_sz,
-			   void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	struct ossp_mixer_arg *arg = carg;
-	int i, rc[2] = { };
-
-	if (prepare_streams())
-		return -EIO;
-
-	for (i = 0; i < 2; i++)
-		if (stream[i])
-			rc[i] = do_mixer(i, arg->vol[i]);
-		else
-			memset(arg->vol[i], -1, sizeof(arg->vol[i]));
-
-	*(struct ossp_mixer_arg *)rarg = *arg;
-	return rc[0] ?: rc[1];
-}
-
-static void context_state_callback(pa_context *cxt, void *userdata)
-{
-	pa_threaded_mainloop_signal(mainloop, 0);
-}
-
-static void context_subscribe_callback(pa_context *context,
-				       pa_subscription_event_type_t type,
-				       uint32_t idx, void *userdata)
-{
-	struct ossp_notify event = { .magic = OSSP_NOTIFY_MAGIC,
-				     .opcode = OSSP_NOTIFY_VOLCHG };
-	ssize_t ret;
-
-	if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) !=
-	    PA_SUBSCRIPTION_EVENT_CHANGE)
-		return;
-
-	ret = write(ossp_notify_fd, &event, sizeof(event));
-	if (ret != sizeof(event) && errno != EPIPE)
-		warn_e(-errno, "write to notify_fd failed");
-}
-
-static ssize_t padsp_open(enum ossp_opcode opcode,
-			  void *carg, void *din, size_t din_sz,
-			  void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	struct ossp_dsp_open_arg *arg = carg;
-	char host_name[128] = "(unknown)", opener[128] = "(unknown)";
-	int state;
-
-	switch (arg->flags & O_ACCMODE) {
-	case O_WRONLY:
-		stream_enabled[PLAY] = 1;
-		break;
-	case O_RDONLY:
-		stream_enabled[REC] = 1;
-		break;
-	case O_RDWR:
-		stream_enabled[PLAY] = 1;
-		stream_enabled[REC] = 1;
-		break;
-	default:
-		assert(0);
-	}
-
-	/* determine stream name */
-	gethostname(host_name, sizeof(host_name) - 1);
-	snprintf(stream_name, sizeof(stream_name), "OSS Proxy %s/%s:%ld",
-		 host_name, ossp_user_name, (long)arg->opener_pid);
-
-	/* create and connect PA context */
-	get_proc_self_info(arg->opener_pid, NULL, opener, sizeof(opener));
-	context = pa_context_new(mainloop_api, opener);
-	if (!context) {
-		err("pa_context_new() failed");
-		return -EIO;
-	}
-
-	pa_context_set_state_callback(context, context_state_callback, NULL);
-	pa_context_set_subscribe_callback(context, context_subscribe_callback,
-					  NULL);
-
-	pa_context_connect(context, NULL, 0, NULL);
-	while (1) {
-		state = pa_context_get_state(context);
-		if (state != PA_CONTEXT_CONNECTING &&
-		    state != PA_CONTEXT_AUTHORIZING &&
-		    state != PA_CONTEXT_SETTING_NAME)
-			break;
-
-		pa_threaded_mainloop_wait(mainloop);
-	}
-
-	if (EXEC_CONTEXT_OP(pa_context_subscribe, context,
-			    PA_SUBSCRIPTION_MASK_SINK_INPUT |
-			    PA_SUBSCRIPTION_MASK_SOURCE))
-		warn_pa("failed to subscribe to context events");
-
-	if (state != PA_CONTEXT_READY) {
-		err_pa("failed to connect context, state=%d", state);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static void mmap_fill_pstg(void)
-{
-	struct ring_buf *stg = &mmap_stg[PLAY];
-	struct ring_buf mmap;
-	uint64_t new_idx = get_mmap_idx(PLAY);
-	size_t bytes, space, size;
-	void *data;
-
-	if (new_idx <= mmap_idx[PLAY])
-		return;
-
-	bytes = new_idx - mmap_idx[PLAY];
-	space = ring_space(stg);
-
-	if (bytes > mmap_size) {
-		dbg0("mmap playback transfer chunk bigger than "
-		     "mmap size (bytes=%zu mmap_size=%zu)", bytes, mmap_size);
-		mmap_sync[PLAY] = 1;
-		bytes = mmap_size;
-	}
-
-	if (bytes > space) {
-		dbg0("mmap playback staging buffer overflow "
-		     "(bytes=%zu space=%zu)", bytes, space);
-		mmap_sync[PLAY] = 1;
-		bytes = space;
-	}
-
-	ring_manual_init(&mmap, mmap_map[PLAY], mmap_size,
-			 new_idx % mmap_size, bytes);
-
-	while ((data = ring_data(&mmap, &size))) {
-		ring_fill(stg, data, size);
-		ring_consume(&mmap, size);
-	}
-
-	mmap_idx[PLAY] = new_idx;
-}
-
-static void mmap_consume_rstg(void)
-{
-	struct ring_buf *stg = &mmap_stg[REC];
-	struct ring_buf mmap;
-	uint64_t new_idx = get_mmap_idx(REC);
-	uint64_t fill_idx = mmap_idx[REC];
-	size_t bytes, space;
-
-	if (new_idx <= mmap_idx[REC])
-		return;
-
-	space = new_idx - mmap_idx[REC];	/* mmapped space to fill in */
-	bytes = ring_bytes(stg);		/* recorded bytes in staging */ 
-
-	if (space > bytes) {
-		if (!mmap_sync[REC])
-			dbg0("mmap recording staging buffer underflow "
-			     "(space=%zu bytes=%zu)", space, bytes);
-		mmap_sync[REC] = 1;
-	}
-
-	if (space > mmap_size) {
-		if (!mmap_sync[REC])
-			dbg0("mmap recording transfer chunk bigger than "
-			     "mmap size (space=%zu mmap_size=%zu)",
-			     bytes, mmap_size);
-		mmap_sync[REC] = 1;
-		space = mmap_size;
-	}
-
-	/* If resync is requested, leave lead bytes in the staging
-	 * buffer and copy everything else such that data is filled
-	 * upto the new_idx.  If there are more bytes in staging than
-	 * available space, those will be dropped.
-	 */
-	if (mmap_sync[REC]) {
-		ssize_t avail = bytes - mmap_lead[REC];
-
-		/* make sure we always have lead bytes in staging */
-		if (avail < 0)
-			goto skip;
-
-		if (avail > space) {
-			dbg0("dropping %zu bytes from record staging buffer",
-			     avail - space);
-			ring_consume(&mmap_stg[REC], avail - space);
-			avail = space;
-		} else {
-			dbg0("skippping %zu bytes in record mmap map",
-			     space - avail);
-			space = avail;
-		}
-
-		assert(new_idx >= avail);
-		fill_idx = new_idx - avail;
-		mmap_sync[REC] = 0;
-	}
-
-	ring_manual_init(&mmap, mmap_map[REC], mmap_size,
-			 fill_idx % mmap_size, 0);
-
-	while (space) {
-		void *data;
-		size_t size, todo;
-
-		data = ring_data(stg, &size);
-		assert(data);
-
-		todo = min(size, space);
-		ring_fill(&mmap, data, todo);
-
-		ring_consume(stg, todo);
-		space -= todo;
-	}
-
- skip:
-	mmap_idx[REC] = new_idx;
-}
-
-static void do_mmap_write(size_t space)
-{
-	struct ring_buf *stg = &mmap_stg[PLAY];
-	size_t todo;
-	void *data;
-
-	space = round_down(space, frame_size);
-	mmap_fill_pstg();
-
-	while (space && (data = ring_data(stg, &todo))) {
-		pa_seek_mode_t mode = PA_SEEK_RELATIVE_END;
-		int64_t offset = 0;
-
-		todo = min(todo, space);
-
-		if (mmap_sync[PLAY]) {
-			mode = PA_SEEK_RELATIVE_ON_READ;
-			offset = (int64_t)mmap_lead[PLAY] - ring_bytes(stg);
-			dbg0("mmap resync, offset=%ld", (long)offset);
-		}
-
-		if (pa_stream_write(stream[PLAY], data, todo, NULL,
-				    offset, mode) < 0) {
-			err_pa("pa_stream_write() failed");
-			padsp_done();
-			return;
-		}
-
-		mmap_sync[PLAY] = 0;
-		ring_consume(stg, todo);
-		space -= todo;
-	}
-}
-
-static void do_mmap_read(size_t bytes)
-{
-	struct ring_buf *stg = &mmap_stg[REC];
-
-	bytes = round_down(bytes, frame_size);
-	mmap_consume_rstg();
-
-	while (bytes) {
-		const void *peek_data;
-		size_t size;
-
-		if (pa_stream_peek(stream[REC], &peek_data, &size)) {
-			err_pa("pa_stream_peek() failed");
-			padsp_done();
-			return;
-		}
-
-		if (!peek_data)
-			break;
-
-		if (size <= ring_space(stg))
-			ring_fill(stg, peek_data, size);
-		else {
-			if (!mmap_sync[REC])
-				dbg0("recording staging buffer overflow, "
-				     "requesting resync");
-			mmap_sync[REC] = 1;
-		}
-
-		pa_stream_drop(stream[REC]);
-		bytes -= size;
-	}
-}
-
-static void stream_rw_callback(pa_stream *s, size_t length, void *userdata)
-{
-	int dir;
-	size_t size;
-
-	if (s == stream[PLAY]) {
-		dir = PLAY;
-		size = pa_stream_writable_size(s);
-		if (mmap_map[PLAY])
-			do_mmap_write(size);
-	} else if (s == stream[REC]) {
-		dir = REC;
-		size = pa_stream_readable_size(s);
-		if (mmap_map[REC])
-			do_mmap_read(size);
-	} else {
-		dbg0("stream_rw_callback(): unknown stream %p PLAY/REC=%p/%p\n",
-		     s, stream[PLAY], stream[REC]);
-		return;
-	}
-
-	if (size < user_frag_size)
-		return;
-	if (stream_waiting)
-		pa_threaded_mainloop_signal(mainloop, 0);
-	if (stream_notify) {
-		struct ossp_notify event = { .magic = OSSP_NOTIFY_MAGIC,
-					     .opcode = OSSP_NOTIFY_POLL };
-		ssize_t ret;
-
-		ret = write(ossp_notify_fd, &event, sizeof(event));
-		if (ret != sizeof(event)) {
-			if (errno != EPIPE)
-				err_e(-errno, "write to notify_fd failed");
-
-			/* This function is run from PA mainloop and
-			 * thus the following padsp_done() won't be
-			 * noticed before the mainthread tries to run
-			 * the next command.  Well, that's good enough.
-			 */
-			padsp_done();
-		}
-		stream_notify = 0;
-	}
-}
-
-static ssize_t padsp_write(enum ossp_opcode opcode,
-			   void *carg, void *din, size_t din_sz,
-			   void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	struct ossp_dsp_rw_arg *arg = carg;
-	size_t size;
-
-	if (prepare_streams() || !stream[PLAY])
-		return -EIO;
-
-	stream_waiting++;
-	while (1) {
-		size = pa_stream_writable_size(stream[PLAY]);
-		if (arg->nonblock || size >= user_frag_size)
-			break;
-		pa_threaded_mainloop_wait(mainloop);
-	}
-	stream_waiting--;
-
-	size = round_down(size, user_frag_size);
-	if (!size)
-		return -EAGAIN;
-
-	size = min(size, din_sz);
-
-	if (pa_stream_write(stream[PLAY], din, size, NULL,
-			    0, PA_SEEK_RELATIVE) < 0) {
-		err_pa("pa_stream_write() failed");
-		return padsp_done();
-	}
-
-	return size;
-}
-
-static ssize_t padsp_read(enum ossp_opcode opcode,
-			  void *carg, void *din, size_t din_sz,
-			  void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	struct ossp_dsp_rw_arg *arg = carg;
-	size_t size;
-	void *data;
-
-	if (prepare_streams() || !stream[REC])
-		return -EIO;
- again:
-	if (!arg->nonblock) {
-		stream_waiting++;
-		while (1) {
-			size = pa_stream_readable_size(stream[REC]);
-			if (size + ring_bytes(&rec_buf) >= user_frag_size)
-				break;
-			pa_threaded_mainloop_wait(mainloop);
-		}
-		stream_waiting--;
-	}
-
-	while (ring_bytes(&rec_buf) < max(user_frag_size, *dout_szp)) {
-		const void *peek_data;
-
-		if (pa_stream_peek(stream[REC], &peek_data, &size) < 0) {
-			err_pa("pa_stream_peek() failed");
-			return padsp_done();
-		}
-
-		if (!peek_data)
-			break;
-
-		if (ring_space(&rec_buf) < size) {
-			size_t bufsz;
-
-			bufsz = ring_size(&rec_buf);
-			bufsz = max(2 * bufsz, bufsz + 2 * size);
-
-			if (ring_resize(&rec_buf, bufsz)) {
-				err("failed to allocate recording buffer");
-				return padsp_done();
-			}
-		}
-
-		ring_fill(&rec_buf, peek_data, size);
-		pa_stream_drop(stream[REC]);
-	}
-
-	size = round_down(ring_bytes(&rec_buf), user_frag_size);
-	if (!size) {
-		if (arg->nonblock)
-			return -EAGAIN;
-		else
-			goto again;
-	}
-
-	*dout_szp = size = min(size, *dout_szp);
-
-	while (size) {
-		size_t cnt;
-
-		data = ring_data(&rec_buf, &cnt);
-		assert(data);
-
-		cnt = min(size, cnt);
-		memcpy(dout, data, cnt);
-		ring_consume(&rec_buf, cnt);
-		dout += cnt;
-		size -= cnt;
-	}
-
-	return *dout_szp;
-}
-
-static ssize_t padsp_poll(enum ossp_opcode opcode,
-			  void *carg, void *din, size_t din_sz,
-			  void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	unsigned revents = 0;
-
-	if (prepare_streams() < 0)
-		return -EIO;
-
-	stream_notify |= *(int *)carg;
-
-	if (stream[PLAY] &&
-	    pa_stream_writable_size(stream[PLAY]) >= user_frag_size)
-		revents |= POLLOUT;
-	if (stream[REC] &&
-	    pa_stream_readable_size(stream[REC]) >= user_frag_size)
-		revents |= POLLIN;
-
-	*(unsigned *)rarg = revents;
-	return 0;
-}
-
-static ssize_t padsp_mmap(enum ossp_opcode opcode,
-			  void *carg, void *din, size_t din_sz,
-			  void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	struct ossp_dsp_mmap_arg *arg = carg;
-	int dir = arg->dir;
-
-	assert(!mmap_map[dir]);
-
-	kill_streams();
-
-	/* arg->size is rounded up to the nearest page boundary.
-	 * There is no way to tell what the actual requested value is
-	 * but assume that it was the reported buffer space if it
-	 * falls into the same page aligned range.
-	 */
-	mmap_raw_size = arg->size;
-	if (user_max_length && user_max_length < mmap_raw_size &&
-	    round_up(mmap_raw_size, page_size) ==
-	    round_up(user_max_length, page_size)) {
-		info("MMAP adjusting raw_size %zu -> %zu",
-		     mmap_raw_size, user_max_length);
-		mmap_raw_size = user_max_length;
-	}
-
-	dbg0("MMAP server-addr=%p sz=%zu", ossp_mmap_addr[dir], mmap_raw_size);
-
-	mmap_map[dir] = ossp_mmap_addr[dir];
-
-	/* if mmapped, only mmapped streams are enabled */
-	stream_enabled[PLAY] = !!mmap_map[PLAY];
-	stream_enabled[REC] = !!mmap_map[REC];
-
-	return 0;
-}
-
-static ssize_t padsp_munmap(enum ossp_opcode opcode,
-			    void *carg, void *din, size_t din_sz,
-			    void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	int dir = *(int *)carg;
-
-	assert(mmap_map[dir]);
-	kill_streams();
-	mmap_map[dir] = NULL;
-	return 0;
-}
-
-static ssize_t padsp_flush(enum ossp_opcode opcode,
-			   void *carg, void *din, size_t din_sz,
-			   void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	flush_streams(opcode == OSSP_DSP_SYNC);
-	return 0;
-}
-
-static ssize_t padsp_post(enum ossp_opcode opcode,
-			  void *carg, void *din, size_t din_sz,
-			  void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	return trigger_streams(1, -1);
-}
-
-static ssize_t padsp_get_param(enum ossp_opcode opcode,
-			       void *carg, void *din, size_t din_sz,
-			       void *rarg, void *dout, size_t *dout_szp,
-			       int tfd)
-{
-	int v = 0;
-
-	switch (opcode) {
-	case OSSP_DSP_GET_RATE:
-		v = sample_spec.rate;
-		break;
-
-	case OSSP_DSP_GET_CHANNELS:
-		v = sample_spec.channels;
-		break;
-
-	case OSSP_DSP_GET_FORMAT:
-		v = fmt_pa_to_oss(sample_spec.format);
-		break;
-
-	case OSSP_DSP_GET_BLKSIZE:
-		if (prepare_streams() < 0)
-			return -EIO;
-		v = user_frag_size;
-		break;
-
-	case OSSP_DSP_GET_FORMATS:
-		v = AFMT_U8 | AFMT_A_LAW | AFMT_MU_LAW | AFMT_S16_LE |
-			AFMT_S16_BE | AFMT_FLOAT | AFMT_S32_LE | AFMT_S32_BE;
-		break;
-
-	case OSSP_DSP_GET_TRIGGER:
-		if (!stream_corked[PLAY])
-			v |= PCM_ENABLE_OUTPUT;
-		if (!stream_corked[REC])
-			v |= PCM_ENABLE_INPUT;
-		break;
-
-	default:
-		assert(0);
-	}
-
-	*(int *)rarg = v;
-
-	return 0;
-}
-
-static ssize_t padsp_set_param(enum ossp_opcode opcode,
-			       void *carg, void *din, size_t din_sz,
-			       void *rarg, void *dout, size_t *dout_szp,
-			       int tfd)
-{
-	pa_sample_spec new_spec = sample_spec;
-	int v = *(int *)carg;
-
-	/* kill the streams before changing parameters */
-	kill_streams();
-
-	switch (opcode) {
-	case OSSP_DSP_SET_RATE:
-		new_spec.rate = v;
-		if (pa_sample_spec_valid(&new_spec))
-			sample_spec = new_spec;
-		v = sample_spec.rate;
-		break;
-
-	case OSSP_DSP_SET_CHANNELS:
-		new_spec.channels = v;
-		if (pa_sample_spec_valid(&new_spec))
-			sample_spec = new_spec;
-		v = sample_spec.channels;
-		break;
-
-	case OSSP_DSP_SET_FORMAT:
-		new_spec.format = fmt_oss_to_pa(v);
-		if (pa_sample_spec_valid(&new_spec))
-			sample_spec = new_spec;
-		v = fmt_pa_to_oss(sample_spec.format);
-		break;
-
-	case OSSP_DSP_SET_SUBDIVISION:
-		if (!v) {
-			v = user_subdivision ?: 1;
-			break;
-		}
-		user_frag_size= 0;
-		user_subdivision = v;
-		break;
-
-	case OSSP_DSP_SET_FRAGMENT:
-		user_subdivision = 0;
-		user_frag_size = 1 << (v & 0xffff);
-		user_max_frags = (v >> 16) & 0xffff;
-		if (user_frag_size < 4)
-			user_frag_size = 4;
-		if (user_max_frags < 2)
-			user_max_frags = 2;
-		break;
-	default:
-		assert(0);
-	}
-
-	if (rarg)
-		*(int *)rarg = v;
-	return 0;
-}
-
-static ssize_t padsp_set_trigger(enum ossp_opcode opcode,
-				 void *carg, void *din, size_t din_sz,
-				 void *rarg, void *dout, size_t *dout_szp,
-				 int fd)
-{
-	int enable = *(int *)carg;
-
-	return trigger_streams(enable & PCM_ENABLE_OUTPUT,
-			       enable & PCM_ENABLE_INPUT);
-}
-
-static ssize_t padsp_get_space(enum ossp_opcode opcode,
-			       void *carg, void *din, size_t din_sz,
-			       void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	int dir = (opcode == OSSP_DSP_GET_OSPACE) ? PLAY : REC;
-	struct audio_buf_info info = { };
-	int rc;
-
-	rc = prepare_streams();
-	if (rc)
-		return -EIO;
-
-	if (mmapped()) {
-		info.fragments = mmap_raw_size / user_frag_size;
-		info.fragstotal = info.fragments;
-		info.fragsize = user_frag_size;
-		info.bytes = mmap_raw_size;
-	} else {
-		size_t space;
-
-		if (dir == PLAY)
-			space = pa_stream_writable_size(stream[PLAY]);
-		else
-			space = pa_stream_readable_size(stream[REC]);
-
-		space = round_down(space, user_frag_size);
-		space = min(space, user_frag_size * user_max_frags);
-
-		info.fragments = space / user_frag_size;
-		info.fragstotal = user_max_frags;
-		info.fragsize = user_frag_size;
-		info.bytes = space;
-	}
-
-	*(struct audio_buf_info *)rarg = info;
-	return 0;
-}
-
-static ssize_t padsp_get_ptr(enum ossp_opcode opcode,
-			     void *carg, void *din, size_t din_sz,
-			     void *rarg, void *dout, size_t *dout_szp, int tfd)
-{
-	int dir = (opcode == OSSP_DSP_GET_OPTR) ? PLAY : REC;
-	struct count_info info = { };
-
-	if (prepare_streams() < 0 || !stream[dir])
-		return -EIO;
-
-	if (mmap_map[dir]) {
-		/* mmap operation in progress, report mmap buffer parameters */
-		if (dir == PLAY)
-			mmap_fill_pstg();
-		else
-			mmap_consume_rstg();
-
-		info.bytes = mmap_idx[dir];
-		info.blocks = (mmap_idx[dir] - mmap_last_idx[dir]) / frame_size;
-		info.ptr = mmap_idx[dir] % mmap_size;
-
-		mmap_last_idx[dir] = mmap_idx[dir];
-	} else {
-		/* simulate pointers using timestamps */
-		double bpus = (double)sample_bps / 1000000;
-		size_t bytes, delta_bytes;
-		pa_usec_t usec, delta;
-
-		if (pa_stream_get_time(stream[dir], &usec) < 0) {
-			warn_pa("pa_stream_get_time() failed");
-			return -EIO;
-		}
-
-		delta = usec - stream_ptr_timestamp[dir];
-		stream_ptr_timestamp[dir] = usec;
-		bytes = bpus * usec;
-		delta_bytes = bpus * delta;
-
-		info.bytes = bytes & INT_MAX;
-		info.blocks = (delta_bytes + frame_size - 1) / frame_size;
-		info.ptr = bytes % user_max_length;
-	}
-
-	*(struct count_info *)rarg = info;
-	return 0;
-}
-
-static ssize_t padsp_get_odelay(enum ossp_opcode opcode,
-				void *carg, void *din, size_t din_sz,
-				void *rarg, void *dout, size_t *dout_szp,
-				int fd)
-{
-	double bpus = (double)sample_bps / 1000000;
-	pa_usec_t usec;
-
-	if (prepare_streams() < 0 || !stream[PLAY])
-		return -EIO;
-
-	if (pa_stream_get_latency(stream[PLAY], &usec, NULL) < 0) {
-		warn_pa("pa_stream_get_latency() failed");
-		return -EIO;
-	}
-
-	*(int *)rarg = bpus * usec;
-	return 0;
-}
-
-static ossp_action_fn_t action_fn_tbl[OSSP_NR_OPCODES] = {
-	[OSSP_MIXER]		= padsp_mixer,
-	[OSSP_DSP_OPEN]		= padsp_open,
-	[OSSP_DSP_READ]		= padsp_read,
-	[OSSP_DSP_WRITE]	= padsp_write,
-	[OSSP_DSP_POLL]		= padsp_poll,
-	[OSSP_DSP_MMAP]		= padsp_mmap,
-	[OSSP_DSP_MUNMAP]	= padsp_munmap,
-	[OSSP_DSP_RESET]	= padsp_flush,
-	[OSSP_DSP_SYNC]		= padsp_flush,
-	[OSSP_DSP_POST]		= padsp_post,
-	[OSSP_DSP_GET_RATE]	= padsp_get_param,
-	[OSSP_DSP_GET_CHANNELS]	= padsp_get_param,
-	[OSSP_DSP_GET_FORMAT]	= padsp_get_param,
-	[OSSP_DSP_GET_BLKSIZE]	= padsp_get_param,
-	[OSSP_DSP_GET_FORMATS]	= padsp_get_param,
-	[OSSP_DSP_SET_RATE]	= padsp_set_param,
-	[OSSP_DSP_SET_CHANNELS]	= padsp_set_param,
-	[OSSP_DSP_SET_FORMAT]	= padsp_set_param,
-	[OSSP_DSP_SET_SUBDIVISION] = padsp_set_param,
-	[OSSP_DSP_SET_FRAGMENT]	= padsp_set_param,
-	[OSSP_DSP_GET_TRIGGER]	= padsp_get_param,
-	[OSSP_DSP_SET_TRIGGER]	= padsp_set_trigger,
-	[OSSP_DSP_GET_OSPACE]	= padsp_get_space,
-	[OSSP_DSP_GET_ISPACE]	= padsp_get_space,
-	[OSSP_DSP_GET_OPTR]	= padsp_get_ptr,
-	[OSSP_DSP_GET_IPTR]	= padsp_get_ptr,
-	[OSSP_DSP_GET_ODELAY]	= padsp_get_odelay,
-};
-
-static int action_pre(void)
-{
-	pa_threaded_mainloop_lock(mainloop);
-	if (fail_code) {
-		pa_threaded_mainloop_unlock(mainloop);
-		return fail_code;
-	}
-	return 0;
-}
-
-static void action_post(void)
-{
-	pa_threaded_mainloop_unlock(mainloop);
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	ossp_slave_init(argc, argv);
-
-	page_size = sysconf(_SC_PAGE_SIZE);
-
-	mainloop = pa_threaded_mainloop_new();
-	if (!mainloop) {
-		err("failed to allocate mainloop");
-		return 1;
-	}
-	mainloop_api = pa_threaded_mainloop_get_api(mainloop);
-
-	if (pa_threaded_mainloop_start(mainloop)) {
-		err("pa_mainloop_start() failed");
-		return 1;
-	}
-
-	/* Okay, now we're open for business */
-	rc = 0;
-	do {
-		rc = ossp_slave_process_command(ossp_cmd_fd, action_fn_tbl,
-						action_pre, action_post);
-	} while (rc > 0 && !fail_code);
-	if (rc)
-		fail_code = rc;
-
-	pa_threaded_mainloop_lock(mainloop);
-
-	kill_streams();
-	if (context) {
-		pa_context_disconnect(context);
-		pa_context_unref(context);
-	}
-
-	pa_threaded_mainloop_unlock(mainloop);
-
-	pa_threaded_mainloop_stop(mainloop);
-	pa_threaded_mainloop_free(mainloop);
-
-	return fail_code ? 1 : 0;
-}
diff --git a/ossp-slave.c b/ossp-slave.c
deleted file mode 100644
index 4c5cb2d..0000000
--- a/ossp-slave.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * ossp-slave - OSS Proxy: Common codes for slaves
- *
- * Copyright (C) 2008-2010  SUSE Linux Products GmbH
- * Copyright (C) 2008-2010  Tejun Heo <tj@kernel.org>
- *
- * This file is released under the GPLv2.
- */
-
-#define _GNU_SOURCE
-
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <signal.h>
-
-#include "ossp-slave.h"
-
-static const char *usage =
-"usage: ossp-SLAVE [options]\n"
-"\n"
-"proxies commands from osspd to pulseaudio\n"
-"\n"
-"options:\n"
-"    -u UID            uid to use\n"
-"    -g GID            gid to use\n"
-"    -c CMD_FD         fd to receive commands from osspd\n"
-"    -n NOTIFY_FD      fd to send async notifications to osspd\n"
-"    -m MMAP_FD        fd to use for mmap\n"
-"    -o MMAP_OFFSET    mmap offset\n"
-"    -s MMAP_SIZE      mmap size\n"
-"    -l LOG_LEVEL      set log level\n"
-"    -t                enable log timestamps\n";
-
-char ossp_user_name[OSSP_USER_NAME_LEN];
-int ossp_cmd_fd = -1, ossp_notify_fd = -1;
-void *ossp_mmap_addr[2];
-
-void ossp_slave_init(int argc, char **argv)
-{
-	int have_uid = 0, have_gid = 0;
-	uid_t uid;
-	gid_t gid;
-	int mmap_fd = -1;
-	off_t mmap_off = 0;
-	size_t mmap_size = 0;
-	int opt;
-	struct passwd *pw, pw_buf;
-	struct sigaction sa;
-	char pw_sbuf[sysconf(_SC_GETPW_R_SIZE_MAX)];
-
-	while ((opt = getopt(argc, argv, "u:g:c:n:m:o:s:l:t")) != -1) {
-		switch (opt) {
-		case 'u':
-			have_uid = 1;
-			uid = strtol(optarg, NULL, 0);
-			break;
-		case 'g':
-			have_gid = 1;
-			gid = strtol(optarg, NULL, 0);
-			break;
-		case 'c':
-			ossp_cmd_fd = strtol(optarg, NULL, 0);
-			break;
-		case 'n':
-			ossp_notify_fd = strtol(optarg, NULL, 0);
-			break;
-		case 'm':
-			mmap_fd = strtol(optarg, NULL, 0);
-			break;
-		case 'o':
-			mmap_off = strtoull(optarg, NULL, 0);
-			break;
-		case 's':
-			mmap_size = strtoul(optarg, NULL, 0);
-			break;
-		case 'l':
-			ossp_log_level = strtol(optarg, NULL, 0);
-			break;
-		case 't':
-			ossp_log_timestamp = 1;
-			break;
-		}
-	}
-
-	if (!have_uid || !have_gid || ossp_cmd_fd < 0 || ossp_notify_fd < 0) {
-		fprintf(stderr, usage);
-		_exit(1);
-	}
-
-	snprintf(ossp_user_name, sizeof(ossp_user_name), "uid%d", uid);
-	if (getpwuid_r(uid, &pw_buf, pw_sbuf, sizeof(pw_sbuf), &pw) == 0)
-		snprintf(ossp_user_name, sizeof(ossp_user_name), "%s",
-			 pw->pw_name);
-
-	snprintf(ossp_log_name, sizeof(ossp_log_name), "ossp-padsp[%s:%d]",
-		 ossp_user_name, getpid());
-
-	if (mmap_fd >= 0) {
-		void *p;
-
-		if (!mmap_off || !mmap_size) {
-			fprintf(stderr, usage);
-			_exit(1);
-		}
-
-		p = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED,
-			 mmap_fd, mmap_off);
-		if (p == MAP_FAILED)
-			fatal_e(-errno, "mmap failed");
-
-		ossp_mmap_addr[PLAY] = p;
-		ossp_mmap_addr[REC] = p + mmap_size / 2;
-		close(mmap_fd);
-	}
-
-	/* mmap done, drop privileges */
-	if (setresgid(gid, gid, gid) || setresuid(uid, uid, uid))
-		fatal_e(-errno, "failed to drop privileges");
-
-	/* block SIGPIPE */
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_IGN;
-	if (sigaction(SIGPIPE, &sa, NULL))
-		fatal_e(-errno, "failed to ignore SIGPIPE");
-}
-
-int ossp_slave_process_command(int cmd_fd,
-			       ossp_action_fn_t const *action_fn_tbl,
-			       int (*action_pre_fn)(void),
-			       void (*action_post_fn)(void))
-{
-	static struct sized_buf carg_sbuf = { }, rarg_sbuf = { };
-	static struct sized_buf din_sbuf = { }, dout_sbuf = { };
-	struct ossp_cmd cmd;
-	int fd = -1;
-	char cmsg_buf[CMSG_SPACE(sizeof(fd))];
-	struct iovec iov = { &cmd, sizeof(cmd) };
-	struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1,
-			      .msg_control = cmsg_buf,
-			      .msg_controllen = sizeof(cmsg_buf) };
-	struct cmsghdr *cmsg;
-	size_t carg_size, din_size, rarg_size, dout_size;
-	char *carg = NULL, *din = NULL, *rarg = NULL, *dout = NULL;
-	struct ossp_reply reply = { .magic = OSSP_REPLY_MAGIC };
-	ssize_t ret;
-
-	ret = recvmsg(cmd_fd, &msg, 0);
-	if (ret == 0)
-		return 0;
-	if (ret < 0) {
-		ret = -errno;
-		err_e(ret, "failed to read command channel");
-		return ret;
-	}
-
-	if (ret != sizeof(cmd)) {
-		err("command struct size mismatch (%zu, should be %zu)",
-		    ret, sizeof(cmd));
-		return -EINVAL;
-	}
-
-	if (cmd.magic != OSSP_CMD_MAGIC) {
-		err("illegal command magic 0x%x", cmd.magic);
-		return -EINVAL;
-	}
-
-	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
-	     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
-		if (cmsg->cmsg_level == SOL_SOCKET &&
-		    cmsg->cmsg_type == SCM_RIGHTS)
-			fd = *(int *)CMSG_DATA(cmsg);
-		else {
-			err("unknown cmsg %d:%d received (opcode %d)",
-			    cmsg->cmsg_level, cmsg->cmsg_type, cmd.opcode);
-			return -EINVAL;
-		}
-	}
-
-	if (cmd.opcode >= OSSP_NR_OPCODES) {
-		err("unknown opcode %d", cmd.opcode);
-		return -EINVAL;
-	}
-
-	carg_size = ossp_arg_sizes[cmd.opcode].carg_size;
-	din_size = cmd.din_size;
-	rarg_size = ossp_arg_sizes[cmd.opcode].rarg_size;
-	dout_size = cmd.dout_size;
-
-	if ((fd >= 0) != ossp_arg_sizes[cmd.opcode].has_fd) {
-		err("fd=%d unexpected for opcode %d", fd, cmd.opcode);
-		return -EINVAL;
-	}
-
-	if (ensure_sbuf_size(&carg_sbuf, carg_size) ||
-	    ensure_sbuf_size(&din_sbuf, din_size) ||
-	    ensure_sbuf_size(&rarg_sbuf, rarg_size) ||
-	    ensure_sbuf_size(&dout_sbuf, dout_size)) {
-		err("failed to allocate command buffers");
-		return -ENOMEM;
-	}
-
-	if (carg_size) {
-		carg = carg_sbuf.buf;
-		ret = read_fill(cmd_fd, carg, carg_size);
-		if (ret < 0)
-			return ret;
-	}
-	if (din_size) {
-		din = din_sbuf.buf;
-		ret = read_fill(cmd_fd, din, din_size);
-		if (ret < 0)
-			return ret;
-	}
-	if (rarg_size)
-		rarg = rarg_sbuf.buf;
-	if (dout_size)
-		dout = dout_sbuf.buf;
-
-	ret = -EINVAL;
-	if (action_fn_tbl[cmd.opcode]) {
-		ret = action_pre_fn();
-		if (ret == 0) {
-			ret = action_fn_tbl[cmd.opcode](cmd.opcode, carg,
-							din, din_size, rarg,
-							dout, &dout_size, fd);
-			action_post_fn();
-		}
-	}
-
-	reply.result = ret;
-	if (ret >= 0)
-		reply.dout_size = dout_size;
-	else {
-		rarg_size = 0;
-		dout_size = 0;
-	}
-
-	if (write_fill(cmd_fd, &reply, sizeof(reply)) < 0 ||
-	    write_fill(cmd_fd, rarg, rarg_size) < 0 ||
-	    write_fill(cmd_fd, dout, dout_size) < 0)
-		return -EIO;
-
-	return 1;
-}
diff --git a/ossp-slave.h b/ossp-slave.h
deleted file mode 100644
index 10c22cd..0000000
--- a/ossp-slave.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * ossp-slave - OSS Proxy: Common codes for slaves
- *
- * Copyright (C) 2008-2010  SUSE Linux Products GmbH
- * Copyright (C) 2008-2010  Tejun Heo <tj@kernel.org>
- *
- * This file is released under the GPLv2.
- */
-
-#ifndef _OSSP_SLAVE_H
-#define _OSSP_SLAVE_H
-
-#include "ossp.h"
-#include "ossp-util.h"
-
-#define OSSP_USER_NAME_LEN	128
-
-extern char ossp_user_name[OSSP_USER_NAME_LEN];
-extern int ossp_cmd_fd, ossp_notify_fd;
-extern void *ossp_mmap_addr[2];
-
-void ossp_slave_init(int argc, char **argv);
-int ossp_slave_process_command(int cmd_fd,
-			       ossp_action_fn_t const *action_fn_tbl,
-			       int (*action_pre_fn)(void),
-			       void (*action_post_fn)(void));
-
-#endif /* _OSSP_SLAVE_H */
diff --git a/ossp-util.c b/ossp-util.c
deleted file mode 100644
index 325cefd..0000000
--- a/ossp-util.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * ossp-util - OSS Proxy: Common utilities
- *
- * Copyright (C) 2008-2010  SUSE Linux Products GmbH
- * Copyright (C) 2008-2010  Tejun Heo <tj@kernel.org>
- *
- * This file is released under the GPLv2.
- */
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <syslog.h>
-#include <unistd.h>
-#include "ossp-util.h"
-
-#define BIT(nr)			(1UL << (nr))
-#define BIT_MASK(nr)		(1UL << ((nr) % BITS_PER_LONG))
-#define BIT_WORD(nr)		((nr) / BITS_PER_LONG)
-#define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
-#define BITOP_WORD(nr)		((nr) / BITS_PER_LONG)
-
-char ossp_log_name[OSSP_LOG_NAME_LEN];
-int ossp_log_level = OSSP_LOG_DFL;
-int ossp_log_timestamp;
-
-static const char *severity_strs[] = {
-	[OSSP_LOG_CRIT]		= "CRIT",
-	[OSSP_LOG_ERR]		= " ERR",
-	[OSSP_LOG_WARN]		= "WARN",
-	[OSSP_LOG_INFO]		= NULL,
-	[OSSP_LOG_DBG0]		= "DBG0",
-	[OSSP_LOG_DBG1]		= "DBG1",
-};
-
-static int severity_map[] = {
-	[OSSP_LOG_CRIT]		= LOG_ERR,
-	[OSSP_LOG_ERR]		= LOG_ERR,
-	[OSSP_LOG_WARN]		= LOG_WARNING,
-	[OSSP_LOG_INFO]		= LOG_INFO,
-	[OSSP_LOG_DBG0]		= LOG_DEBUG,
-	[OSSP_LOG_DBG1]		= LOG_DEBUG,
-};
-
-void log_msg(int severity, const char *fmt, ...)
-{
-	static int syslog_opened = 0;
-	char buf[1024];
-	size_t len = sizeof(buf), off = 0;
-	va_list ap;
-
-	if (severity > abs(ossp_log_level))
-		return;
-
-	if (ossp_log_level < 0 && !syslog_opened)
-		openlog(ossp_log_name, 0, LOG_DAEMON);
-
-	assert(severity >= 0 && severity < ARRAY_SIZE(severity_strs));
-
-	if (ossp_log_timestamp) {
-		static uint64_t start;
-		uint64_t now;
-		struct timeval tv;
-		gettimeofday(&tv, NULL);
-		now = tv.tv_sec * 1000 + tv.tv_usec / 1000;
-		if (!start)
-			start = now;
-
-		off += snprintf(buf + off, len - off, "<%08"PRIu64"> ",
-				now - start);
-	}
-
-	if (ossp_log_level > 0) {
-		char sev_buf[16] = "";
-		if (severity_strs[severity])
-			snprintf(sev_buf, sizeof(sev_buf), " %s",
-				 severity_strs[severity]);
-		off += snprintf(buf + off, len - off, "%s%s: ",
-				ossp_log_name, sev_buf);
-	} else if (severity_strs[severity])
-		off += snprintf(buf + off, len - off, "%s ",
-				severity_strs[severity]);
-
-	va_start(ap, fmt);
-	off += vsnprintf(buf + off, len - off, fmt, ap);
-	va_end(ap);
-
-	off += snprintf(buf + off, len - off, "\n");
-
-	if (ossp_log_level > 0)
-		fputs(buf, stderr);
-	else
-		syslog(severity_map[severity], "%s", buf);
-}
-
-int read_fill(int fd, void *buf, size_t size)
-{
-	while (size) {
-		ssize_t ret;
-		int rc;
-
-		ret = read(fd, buf, size);
-		if (ret <= 0) {
-			if (ret == 0)
-				rc = -EIO;
-			else
-				rc = -errno;
-			err_e(rc, "failed to read_fill %zu bytes from fd %d",
-			      size, fd);
-			return rc;
-		}
-		buf += ret;
-		size -= ret;
-	}
-	return 0;
-}
-
-int write_fill(int fd, const void *buf, size_t size)
-{
-	while (size) {
-		ssize_t ret;
-		int rc;
-
-		ret = write(fd, buf, size);
-		if (ret <= 0) {
-			if (ret == 0)
-				rc = -EIO;
-			else
-				rc = -errno;
-			err_e(rc, "failed to write_fill %zu bytes to fd %d",
-			      size, fd);
-			return rc;
-		}
-		buf += ret;
-		size -= ret;
-	}
-	return 0;
-}
-
-void ring_fill(struct ring_buf *ring, const void *buf, size_t size)
-{
-	size_t tail;
-
-	assert(ring_space(ring) >= size);
-
-	tail = (ring->head + ring->size - ring->bytes) % ring->size;
-
-	if (ring->head >= tail) {
-		size_t todo = min(size, ring->size - ring->head);
-
-		memcpy(ring->buf + ring->head, buf, todo);
-		ring->head = (ring->head + todo) % ring->size;
-		ring->bytes += todo;
-		buf += todo;
-		size -= todo;
-	}
-
-	assert(ring->size - ring->head >= size);
-	memcpy(ring->buf + ring->head, buf, size);
-	ring->head += size;
-	ring->bytes += size;
-}
-
-void *ring_data(struct ring_buf *ring, size_t *sizep)
-{
-	size_t tail;
-
-	if (!ring->bytes)
-		return NULL;
-
-	tail = (ring->head + ring->size - ring->bytes) % ring->size;
-
-	*sizep = min(ring->bytes, ring->size - tail);
-	return ring->buf + tail;
-}
-
-int ring_resize(struct ring_buf *ring, size_t new_size)
-{
-	struct ring_buf new_ring = { .size = new_size };
-	void *p;
-	size_t size;
-
-	if (ring_bytes(ring) > new_size)
-		return -ENOSPC;
-
-	new_ring.buf = calloc(1, new_size);
-	if (new_size && !new_ring.buf)
-		return -ENOMEM;
-
-	while ((p = ring_data(ring, &size))) {
-		ring_fill(&new_ring, p, size);
-		ring_consume(ring, size);
-	}
-
-	free(ring->buf);
-	*ring = new_ring;
-	return 0;
-}
-
-int ensure_sbuf_size(struct sized_buf *sbuf, size_t size)
-{
-	char *new_buf;
-
-	if (sbuf->size >= size)
-		return 0;
-
-	new_buf = realloc(sbuf->buf, size);
-	if (size && !new_buf)
-		return -ENOMEM;
-
-	sbuf->buf = new_buf;
-	sbuf->size = size;
-	return 0;
-}
-
-static unsigned long __ffs(unsigned long word)
-{
-	int num = 0;
-
-	if (BITS_PER_LONG == 64) {
-		if ((word & 0xffffffff) == 0) {
-			num += 32;
-			word >>= 32;
-		}
-	}
-
-	if ((word & 0xffff) == 0) {
-		num += 16;
-		word >>= 16;
-	}
-	if ((word & 0xff) == 0) {
-		num += 8;
-		word >>= 8;
-	}
-	if ((word & 0xf) == 0) {
-		num += 4;
-		word >>= 4;
-	}
-	if ((word & 0x3) == 0) {
-		num += 2;
-		word >>= 2;
-	}
-	if ((word & 0x1) == 0)
-		num += 1;
-	return num;
-}
-
-#define ffz(x)  __ffs(~(x))
-
-unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
-				 unsigned long offset)
-{
-	const unsigned long *p = addr + BITOP_WORD(offset);
-	unsigned long result = offset & ~(BITS_PER_LONG-1);
-	unsigned long tmp;
-
-	if (offset >= size)
-		return size;
-	size -= result;
-	offset %= BITS_PER_LONG;
-	if (offset) {
-		tmp = *(p++);
-		tmp |= ~0UL >> (BITS_PER_LONG - offset);
-		if (size < BITS_PER_LONG)
-			goto found_first;
-		if (~tmp)
-			goto found_middle;
-		size -= BITS_PER_LONG;
-		result += BITS_PER_LONG;
-	}
-	while (size & ~(BITS_PER_LONG-1)) {
-		if (~(tmp = *(p++)))
-			goto found_middle;
-		result += BITS_PER_LONG;
-		size -= BITS_PER_LONG;
-	}
-	if (!size)
-		return result;
-	tmp = *p;
-
-found_first:
-	tmp |= ~0UL << size;
-	if (tmp == ~0UL)	/* Are any bits zero? */
-		return result + size;	/* Nope. */
-found_middle:
-	return result + ffz(tmp);
-}
-
-void __set_bit(int nr, volatile unsigned long *addr)
-{
-	unsigned long mask = BIT_MASK(nr);
-	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
-
-	*p  |= mask;
-}
-
-void __clear_bit(int nr, volatile unsigned long *addr)
-{
-	unsigned long mask = BIT_MASK(nr);
-	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
-
-	*p &= ~mask;
-}
-
-int get_proc_self_info(pid_t pid, pid_t *ppid_r,
-		       char *cmd_buf, size_t cmd_buf_sz)
-
-{
-	char path[64], buf[4096];
-	int fd = -1;
-	char *cmd_start, *cmd_end, *ppid_start, *end;
-	ssize_t ret;
-	pid_t ppid;
-	int i, rc;
-
-	snprintf(path, sizeof(path), "/proc/%ld/stat", (long)pid);
-	fd = open(path, O_RDONLY);
-	if (fd < 0) {
-		rc = -errno;
-		goto out;
-	}
-
-	ret = read(fd, buf, sizeof(buf));
-	if (ret < 0)
-		goto out;
-	if (ret == sizeof(buf)) {
-		rc = -EOVERFLOW;
-		goto out;
-	}
-	buf[ret] = '\0';
-
-	rc = -EINVAL;
-	cmd_start = strchr(buf, '(');
-	cmd_end = strrchr(buf, ')');
-	if (!cmd_start || !cmd_end)
-		goto out;
-	cmd_start++;
-
-	ppid_start = cmd_end;
-	for (i = 0; i < 3; i++) {
-		ppid_start = strchr(ppid_start, ' ');
-		if (!ppid_start)
-			goto out;
-		ppid_start++;
-	}
-
-	ppid = strtoul(ppid_start, &end, 10);
-	if (end == ppid_start || *end != ' ')
-		goto out;
-
-	if (ppid_r)
-		*ppid_r = ppid;
-	if (cmd_buf) {
-		size_t len = min_t(size_t, cmd_end - cmd_start, cmd_buf_sz - 1);
-		memcpy(cmd_buf, cmd_start, len);
-		cmd_buf[len] = '\0';
-	}
-
-	rc = 0;
- out:
-	close(fd);
-
-	return rc;
-}
diff --git a/ossp-util.h b/ossp-util.h
deleted file mode 100644
index f48d022..0000000
--- a/ossp-util.h
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- * ossp-util - OSS Proxy: Common utilities
- *
- * Copyright (C) 2008-2010  SUSE Linux Products GmbH
- * Copyright (C) 2008-2010  Tejun Heo <tj@kernel.org>
- *
- * This file is released under the GPLv2.
- */
-
-#ifndef _OSSP_UTIL_H
-#define _OSSP_UTIL_H
-
-#include <assert.h>
-#include <stddef.h>
-#include <string.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include "ossp.h"
-
-#define OSSP_LOG_NAME_LEN	128
-
-enum {
-	OSSP_LOG_CRIT	= 1,
-	OSSP_LOG_ERR,
-	OSSP_LOG_WARN,
-	OSSP_LOG_INFO,
-	OSSP_LOG_DFL	= OSSP_LOG_INFO, /* default log level */
-	OSSP_LOG_DBG0,
-	OSSP_LOG_DBG1,
-	OSSP_LOG_MAX	= OSSP_LOG_DBG1,
-};
-
-extern char ossp_log_name[OSSP_LOG_NAME_LEN];
-extern int ossp_log_level;
-extern int ossp_log_timestamp;
-
-#define BITS_PER_BYTE		8
-#define BITS_PER_LONG		(BITS_PER_BYTE * sizeof(long))
-#define DIV_ROUND_UP(n,d)	(((n) + (d) - 1) / (d))
-#define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
-
-/* ARRAY_SIZE and min/max macros stolen from linux/kernel.h */
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-
-#define min(x, y) ({				\
-	typeof(x) _min1 = (x);			\
-	typeof(y) _min2 = (y);			\
-	(void) (&_min1 == &_min2);		\
-	_min1 < _min2 ? _min1 : _min2; })
-
-#define max(x, y) ({				\
-	typeof(x) _max1 = (x);			\
-	typeof(y) _max2 = (y);			\
-	(void) (&_max1 == &_max2);		\
-	_max1 > _max2 ? _max1 : _max2; })
-
-#define min_t(type, x, y) ({			\
-	type __min1 = (x);			\
-	type __min2 = (y);			\
-	__min1 < __min2 ? __min1: __min2; })
-
-#define max_t(type, x, y) ({			\
-	type __max1 = (x);			\
-	type __max2 = (y);			\
-	__max1 > __max2 ? __max1: __max2; })
-
-void log_msg(int severity, const char *fmt, ...)
-	__attribute__ ((format (printf, 2, 3)));
-
-#define fatal(fmt, args...) do {					\
-	log_msg(OSSP_LOG_CRIT, fmt , ##args);				\
-	_exit(1);							\
-} while (0)
-#define err(fmt, args...)		log_msg(OSSP_LOG_ERR, fmt , ##args)
-#define warn(fmt, args...)		log_msg(OSSP_LOG_WARN, fmt , ##args)
-#define info(fmt, args...)		log_msg(OSSP_LOG_INFO, fmt , ##args)
-#define dbg0(fmt, args...)		log_msg(OSSP_LOG_DBG0, fmt , ##args)
-#define dbg1(fmt, args...)		log_msg(OSSP_LOG_DBG1, fmt , ##args)
-
-#define fatal_e(e, fmt, args...)	\
-	fatal(fmt" (%s)" , ##args, strerror(-(e)))
-#define err_e(e, fmt, args...)	\
-	err(fmt" (%s)" , ##args, strerror(-(e)))
-#define warn_e(e, fmt, args...)	\
-	warn(fmt" (%s)" , ##args, strerror(-(e)))
-#define info_e(e, fmt, args...)	\
-	info(fmt" (%s)" , ##args, strerror(-(e)))
-#define dbg0_e(e, fmt, args...)	\
-	dbg0(fmt" (%s)" , ##args, strerror(-(e)))
-#define dbg1_e(e, fmt, args...)	\
-	dbg1(fmt" (%s)" , ##args, strerror(-(e)))
-
-struct ring_buf {
-	char		*buf;
-	size_t		size;
-	size_t		head;
-	size_t		bytes;
-};
-
-static inline size_t ring_size(struct ring_buf *ring)
-{
-	return ring->size;
-}
-
-static inline size_t ring_bytes(struct ring_buf *ring)
-{
-	return ring->bytes;
-}
-
-static inline size_t ring_space(struct ring_buf *ring)
-{
-	return ring->size - ring->bytes;
-}
-
-static inline void ring_consume(struct ring_buf *ring, size_t size)
-{
-	assert(ring->bytes >= size);
-	ring->bytes -= size;
-}
-
-static inline void ring_manual_init(struct ring_buf *ring, void *buf,
-				    size_t size, size_t head, size_t bytes)
-{
-	ring->buf = buf;
-	ring->size = size;
-	ring->head = head;
-	ring->bytes = bytes;
-}
-
-void ring_fill(struct ring_buf *ring, const void *buf, size_t size);
-void *ring_data(struct ring_buf *ring, size_t *sizep);
-int ring_resize(struct ring_buf *ring, size_t new_size);
-
-struct sized_buf {
-	char		*buf;
-	size_t		size;
-};
-
-int ensure_sbuf_size(struct sized_buf *sbuf, size_t size);
-
-int read_fill(int fd, void *buf, size_t size);
-int write_fill(int fd, const void *buf, size_t size);
-
-/*
- * Bitops lifted from linux asm-generic implementation.
- */
-unsigned long find_next_zero_bit(const unsigned long *addr, unsigned
-				 long size, unsigned long offset);
-#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
-extern void __set_bit(int nr, volatile unsigned long *addr);
-extern void __clear_bit(int nr, volatile unsigned long *addr);
-
-typedef ssize_t (*ossp_action_fn_t)(enum ossp_opcode opcode,
-				    void *carg, void *din, size_t din_sz,
-				    void *rarg, void *dout, size_t *dout_szp,
-				    int fd);
-
-int get_proc_self_info(pid_t tid, pid_t *pgrp,
-		       char *cmd_buf, size_t cmd_buf_sz);
-
-/*
- * Doubly linked list handling code shamelessly stolen from the Linux
- * kernel 2.6.26 include/linux/list.h.
- */
-
-/**
- * container_of - cast a member of a structure out to the containing structure
- * @ptr:	the pointer to the member.
- * @type:	the type of the container struct this is embedded in.
- * @member:	the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({			\
-	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
-	(type *)( (char *)__mptr - offsetof(type,member) );})
-
-#define LIST_POISON1  ((void *) 0x00100100)
-#define LIST_POISON2  ((void *) 0x00200200)
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
-	struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
-	struct list_head name = LIST_HEAD_INIT(name)
-
-static inline void INIT_LIST_HEAD(struct list_head *list)
-{
-	list->next = list;
-	list->prev = list;
-}
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
-			      struct list_head *prev,
-			      struct list_head *next)
-{
-	next->prev = new;
-	new->next = next;
-	new->prev = prev;
-	prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
-	__list_add(new, head, head->next);
-}
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
-	__list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head * prev, struct list_head * next)
-{
-	next->prev = prev;
-	prev->next = next;
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty() on entry does not return true after this, the entry is
- * in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
-{
-	__list_del(entry->prev, entry->next);
-	entry->next = LIST_POISON1;
-	entry->prev = LIST_POISON2;
-}
-
-/**
- * list_replace - replace old entry by new one
- * @old : the element to be replaced
- * @new : the new element to insert
- *
- * If @old was empty, it will be overwritten.
- */
-static inline void list_replace(struct list_head *old,
-				struct list_head *new)
-{
-	new->next = old->next;
-	new->next->prev = new;
-	new->prev = old->prev;
-	new->prev->next = new;
-}
-
-static inline void list_replace_init(struct list_head *old,
-					struct list_head *new)
-{
-	list_replace(old, new);
-	INIT_LIST_HEAD(old);
-}
-
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
- */
-static inline void list_del_init(struct list_head *entry)
-{
-	__list_del(entry->prev, entry->next);
-	INIT_LIST_HEAD(entry);
-}
-
-/**
- * list_move - delete from one list and add as another's head
- * @list: the entry to move
- * @head: the head that will precede our entry
- */
-static inline void list_move(struct list_head *list, struct list_head *head)
-{
-	__list_del(list->prev, list->next);
-	list_add(list, head);
-}
-
-/**
- * list_move_tail - delete from one list and add as another's tail
- * @list: the entry to move
- * @head: the head that will follow our entry
- */
-static inline void list_move_tail(struct list_head *list,
-				  struct list_head *head)
-{
-	__list_del(list->prev, list->next);
-	list_add_tail(list, head);
-}
-
-/**
- * list_is_last - tests whether @list is the last entry in list @head
- * @list: the entry to test
- * @head: the head of the list
- */
-static inline int list_is_last(const struct list_head *list,
-				const struct list_head *head)
-{
-	return list->next == head;
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(const struct list_head *head)
-{
-	return head->next == head;
-}
-
-/**
- * list_empty_careful - tests whether a list is empty and not being modified
- * @head: the list to test
- *
- * Description:
- * tests whether a list is empty _and_ checks that no other CPU might be
- * in the process of modifying either member (next or prev)
- *
- * NOTE: using list_empty_careful() without synchronization
- * can only be safe if the only activity that can happen
- * to the list entry is list_del_init(). Eg. it cannot be used
- * if another CPU could re-list_add() it.
- */
-static inline int list_empty_careful(const struct list_head *head)
-{
-	struct list_head *next = head->next;
-	return (next == head) && (next == head->prev);
-}
-
-/**
- * list_is_singular - tests whether a list has just one entry.
- * @head: the list to test.
- */
-static inline int list_is_singular(const struct list_head *head)
-{
-	return !list_empty(head) && (head->next == head->prev);
-}
-
-static inline void __list_splice(const struct list_head *list,
-				 struct list_head *head)
-{
-	struct list_head *first = list->next;
-	struct list_head *last = list->prev;
-	struct list_head *at = head->next;
-
-	first->prev = head;
-	head->next = first;
-
-	last->next = at;
-	at->prev = last;
-}
-
-/**
- * list_splice - join two lists
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-static inline void list_splice(const struct list_head *list,
-				struct list_head *head)
-{
-	if (!list_empty(list))
-		__list_splice(list, head);
-}
-
-/**
- * list_splice_init - join two lists and reinitialise the emptied list.
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- *
- * The list at @list is reinitialised
- */
-static inline void list_splice_init(struct list_head *list,
-				    struct list_head *head)
-{
-	if (!list_empty(list)) {
-		__list_splice(list, head);
-		INIT_LIST_HEAD(list);
-	}
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr:	the &struct list_head pointer.
- * @type:	the type of the struct this is embedded in.
- * @member:	the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
-	container_of(ptr, type, member)
-
-/**
- * list_first_entry - get the first element from a list
- * @ptr:	the list head to take the element from.
- * @type:	the type of the struct this is embedded in.
- * @member:	the name of the list_struct within the struct.
- *
- * Note, that list is expected to be not empty.
- */
-#define list_first_entry(ptr, type, member) \
-	list_entry((ptr)->next, type, member)
-
-/**
- * list_for_each	-	iterate over a list
- * @pos:	the &struct list_head to use as a loop cursor.
- * @head:	the head for your list.
- */
-#define list_for_each(pos, head) \
-	for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * list_for_each_prev	-	iterate over a list backwards
- * @pos:	the &struct list_head to use as a loop cursor.
- * @head:	the head for your list.
- */
-#define list_for_each_prev(pos, head) \
-	for (pos = (head)->prev; pos != (head); pos = pos->prev)
-
-/**
- * list_for_each_safe - iterate over a list safe against removal of list entry
- * @pos:	the &struct list_head to use as a loop cursor.
- * @n:		another &struct list_head to use as temporary storage
- * @head:	the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
-	for (pos = (head)->next, n = pos->next; pos != (head); \
-		pos = n, n = pos->next)
-
-/**
- * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
- * @pos:	the &struct list_head to use as a loop cursor.
- * @n:		another &struct list_head to use as temporary storage
- * @head:	the head for your list.
- */
-#define list_for_each_prev_safe(pos, n, head) \
-	for (pos = (head)->prev, n = pos->prev; \
-	     pos != (head); pos = n, n = pos->prev)
-
-/**
- * list_for_each_entry	-	iterate over list of given type
- * @pos:	the type * to use as a loop cursor.
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- */
-#define list_for_each_entry(pos, head, member)				\
-	for (pos = list_entry((head)->next, typeof(*pos), member);	\
-	     &pos->member != (head);				 	\
-	     pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_reverse - iterate backwards over list of given type.
- * @pos:	the type * to use as a loop cursor.
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- */
-#define list_for_each_entry_reverse(pos, head, member)			\
-	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
-	     &pos->member != (head);					\
-	     pos = list_entry(pos->member.prev, typeof(*pos), member))
-
-/**
- * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
- * @pos:	the type * to use as a start point
- * @head:	the head of the list
- * @member:	the name of the list_struct within the struct.
- *
- * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
- */
-#define list_prepare_entry(pos, head, member) \
-	((pos) ? : list_entry(head, typeof(*pos), member))
-
-/**
- * list_for_each_entry_continue - continue iteration over list of given type
- * @pos:	the type * to use as a loop cursor.
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Continue to iterate over list of given type, continuing after
- * the current position.
- */
-#define list_for_each_entry_continue(pos, head, member) 		\
-	for (pos = list_entry(pos->member.next, typeof(*pos), member);	\
-	     &pos->member != (head);					\
-	     pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_continue_reverse - iterate backwards from the given point
- * @pos:	the type * to use as a loop cursor.
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Start to iterate over list of given type backwards, continuing after
- * the current position.
- */
-#define list_for_each_entry_continue_reverse(pos, head, member)		\
-	for (pos = list_entry(pos->member.prev, typeof(*pos), member);	\
-	     &pos->member != (head);					\
-	     pos = list_entry(pos->member.prev, typeof(*pos), member))
-
-/**
- * list_for_each_entry_from - iterate over list of given type from the current point
- * @pos:	the type * to use as a loop cursor.
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Iterate over list of given type, continuing from current position.
- */
-#define list_for_each_entry_from(pos, head, member) 			\
-	for (; &pos->member != (head);					\
-	     pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos:	the type * to use as a loop cursor.
- * @n:		another type * to use as temporary storage
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member)			\
-	for (pos = list_entry((head)->next, typeof(*pos), member),	\
-		n = list_entry(pos->member.next, typeof(*pos), member);	\
-	     &pos->member != (head); 					\
-	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_continue
- * @pos:	the type * to use as a loop cursor.
- * @n:		another type * to use as temporary storage
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Iterate over list of given type, continuing after current point,
- * safe against removal of list entry.
- */
-#define list_for_each_entry_safe_continue(pos, n, head, member) 		\
-	for (pos = list_entry(pos->member.next, typeof(*pos), member), 		\
-		n = list_entry(pos->member.next, typeof(*pos), member);		\
-	     &pos->member != (head);						\
-	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_from
- * @pos:	the type * to use as a loop cursor.
- * @n:		another type * to use as temporary storage
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Iterate over list of given type from current point, safe against
- * removal of list entry.
- */
-#define list_for_each_entry_safe_from(pos, n, head, member) 			\
-	for (n = list_entry(pos->member.next, typeof(*pos), member);		\
-	     &pos->member != (head);						\
-	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_reverse
- * @pos:	the type * to use as a loop cursor.
- * @n:		another type * to use as temporary storage
- * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
- *
- * Iterate backwards over list of given type, safe against removal
- * of list entry.
- */
-#define list_for_each_entry_safe_reverse(pos, n, head, member)		\
-	for (pos = list_entry((head)->prev, typeof(*pos), member),	\
-		n = list_entry(pos->member.prev, typeof(*pos), member);	\
-	     &pos->member != (head); 					\
-	     pos = n, n = list_entry(n->member.prev, typeof(*n), member))
-
-#endif /*_OSSP_UTIL_H*/
diff --git a/ossp.c b/ossp.c
deleted file mode 100644
index 96f98fa..0000000
--- a/ossp.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * ossp - OSS Proxy: emulate OSS device using CUSE
- *
- * Copyright (C) 2008-2010  SUSE Linux Products GmbH
- * Copyright (C) 2008-2010  Tejun Heo <tj@kernel.org>
- *
- * This file is released under the GPLv2.
- */
-
-#include "ossp.h"
-
-const struct ossp_arg_size ossp_arg_sizes[OSSP_NR_OPCODES] = {
-	[OSSP_MIXER]		= { sizeof(struct ossp_mixer_arg),
-				    sizeof(struct ossp_mixer_arg), 0 },
-
-	[OSSP_DSP_OPEN]		= { sizeof(struct ossp_dsp_open_arg), 0, 0 },
-	[OSSP_DSP_READ]		= { sizeof(struct ossp_dsp_rw_arg), 0, 0 },
-	[OSSP_DSP_WRITE]	= { sizeof(struct ossp_dsp_rw_arg), 0, 0 },
-	[OSSP_DSP_POLL]		= { sizeof(int), sizeof(unsigned), 0 },
-	[OSSP_DSP_MMAP]		= { sizeof(struct ossp_dsp_mmap_arg), 0, 0 },
-	[OSSP_DSP_MUNMAP]	= { sizeof(int), 0, 0 },
-
-	[OSSP_DSP_RESET]	= { 0, 0, 0 },
-	[OSSP_DSP_SYNC]		= { 0, 0, 0 },
-	[OSSP_DSP_POST]		= { 0, 0, 0 },
-	[OSSP_DSP_GET_RATE]	= { 0, sizeof(int), 0 },
-	[OSSP_DSP_GET_CHANNELS]	= { 0, sizeof(int), 0 },
-	[OSSP_DSP_GET_FORMAT]	= { 0, sizeof(int), 0 },
-	[OSSP_DSP_GET_BLKSIZE]	= { 0, sizeof(int), 0 },
-	[OSSP_DSP_GET_FORMATS]	= { 0, sizeof(int), 0 },
-	[OSSP_DSP_SET_RATE]	= { sizeof(int), sizeof(int), 0 },
-	[OSSP_DSP_SET_CHANNELS]	= { sizeof(int), sizeof(int), 0 },
-	[OSSP_DSP_SET_FORMAT]	= { sizeof(int), sizeof(int), 0 },
-	[OSSP_DSP_SET_SUBDIVISION] = { sizeof(int), sizeof(int), 0 },
-	[OSSP_DSP_SET_FRAGMENT]	= { sizeof(int), 0, 0 },
-	[OSSP_DSP_GET_TRIGGER]	= { 0, sizeof(int), 0 },
-	[OSSP_DSP_SET_TRIGGER]	= { sizeof(int), 0, 0 },
-	[OSSP_DSP_GET_OSPACE]	= { 0, sizeof(struct audio_buf_info), 0 },
-	[OSSP_DSP_GET_ISPACE]	= { 0, sizeof(struct audio_buf_info), 0 },
-	[OSSP_DSP_GET_OPTR]	= { 0, sizeof(struct count_info), 0 },
-	[OSSP_DSP_GET_IPTR]	= { 0, sizeof(struct count_info), 0 },
-	[OSSP_DSP_GET_ODELAY]	= { 0, sizeof(int), 0 },
-};
-
-const char *ossp_cmd_str[OSSP_NR_OPCODES] = {
-	[OSSP_MIXER]		= "MIXER",
-
-	[OSSP_DSP_OPEN]		= "OPEN",
-	[OSSP_DSP_READ]		= "READ",
-	[OSSP_DSP_WRITE]	= "WRITE",
-	[OSSP_DSP_POLL]		= "POLL",
-	[OSSP_DSP_MMAP]		= "MMAP",
-	[OSSP_DSP_MUNMAP]	= "MUNMAP",
-
-	[OSSP_DSP_RESET]	= "RESET",
-	[OSSP_DSP_SYNC]		= "SYNC",
-	[OSSP_DSP_POST]		= "POST",
-
-	[OSSP_DSP_GET_RATE]	= "GET_RATE",
-	[OSSP_DSP_GET_CHANNELS]	= "GET_CHANNELS",
-	[OSSP_DSP_GET_FORMAT]	= "GET_FORMAT",
-	[OSSP_DSP_GET_BLKSIZE]	= "GET_BLKSIZE",
-	[OSSP_DSP_GET_FORMATS]	= "GET_FORMATS",
-	[OSSP_DSP_SET_RATE]	= "SET_RATE",
-	[OSSP_DSP_SET_CHANNELS]	= "SET_CHANNELS",
-	[OSSP_DSP_SET_FORMAT]	= "SET_FORMAT",
-	[OSSP_DSP_SET_SUBDIVISION] = "SET_BUSDIVISION",
-
-	[OSSP_DSP_SET_FRAGMENT]	= "SET_FRAGMENT",
-	[OSSP_DSP_GET_TRIGGER]	= "GET_TRIGGER",
-	[OSSP_DSP_SET_TRIGGER]	= "SET_TRIGGER",
-	[OSSP_DSP_GET_OSPACE]	= "GET_OSPACE",
-	[OSSP_DSP_GET_ISPACE]	= "GET_ISPACE",
-	[OSSP_DSP_GET_OPTR]	= "GET_OPTR",
-	[OSSP_DSP_GET_IPTR]	= "GET_IPTR",
-	[OSSP_DSP_GET_ODELAY]	= "GET_ODELAY",
-};
-
-const char *ossp_notify_str[OSSP_NR_NOTIFY_OPCODES] = {
-	[OSSP_NOTIFY_POLL]	= "POLL",
-	[OSSP_NOTIFY_OBITUARY]	= "OBITUARY",
-	[OSSP_NOTIFY_VOLCHG]	= "VOLCHG",
-};
diff --git a/ossp.h b/ossp.h
deleted file mode 100644
index 9d03e63..0000000
--- a/ossp.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * ossp - OSS Proxy: emulate OSS device using CUSE
- *
- * Copyright (C) 2008-2010  SUSE Linux Products GmbH
- * Copyright (C) 2008-2010  Tejun Heo <tj@kernel.org>
- *
- * This file is released under the GPLv2.
- */
-
-#ifndef _OSSP_H
-#define _OSSP_H
-
-#include <sys/types.h>
-#include <inttypes.h>
-#include <sys/soundcard.h>
-
-#define OSSP_VERSION		"1.3.2"
-#define OSSP_CMD_MAGIC		0xdeadbeef
-#define OSSP_REPLY_MAGIC	0xbeefdead
-#define OSSP_NOTIFY_MAGIC	0xbebebebe
-
-#define PLAY			0
-#define REC			1
-#define LEFT			0
-#define RIGHT			1
-
-enum ossp_opcode {
-	OSSP_MIXER,
-
-	OSSP_DSP_OPEN,
-	OSSP_DSP_READ,
-	OSSP_DSP_WRITE,
-	OSSP_DSP_POLL,
-	OSSP_DSP_MMAP,
-	OSSP_DSP_MUNMAP,
-
-	OSSP_DSP_RESET,
-	OSSP_DSP_SYNC,
-	OSSP_DSP_POST,
-
-	OSSP_DSP_GET_RATE,
-	OSSP_DSP_GET_CHANNELS,
-	OSSP_DSP_GET_FORMAT,
-	OSSP_DSP_GET_BLKSIZE,
-	OSSP_DSP_GET_FORMATS,
-	OSSP_DSP_SET_RATE,
-	OSSP_DSP_SET_CHANNELS,
-	OSSP_DSP_SET_FORMAT,
-	OSSP_DSP_SET_SUBDIVISION,
-
-	OSSP_DSP_SET_FRAGMENT,
-	OSSP_DSP_GET_TRIGGER,
-	OSSP_DSP_SET_TRIGGER,
-	OSSP_DSP_GET_OSPACE,
-	OSSP_DSP_GET_ISPACE,
-	OSSP_DSP_GET_OPTR,
-	OSSP_DSP_GET_IPTR,
-	OSSP_DSP_GET_ODELAY,
-
-	OSSP_NR_OPCODES,
-};
-
-enum ossp_notify_opcode {
-	OSSP_NOTIFY_POLL,
-	OSSP_NOTIFY_OBITUARY,
-	OSSP_NOTIFY_VOLCHG,
-
-	OSSP_NR_NOTIFY_OPCODES,
-};
-
-struct ossp_mixer_arg {
-	int			vol[2][2];
-};
-
-struct ossp_dsp_open_arg {
-	int			flags;
-	pid_t			opener_pid;
-};
-
-struct ossp_dsp_rw_arg {
-	unsigned		nonblock:1;
-};
-
-struct ossp_dsp_mmap_arg {
-	int			dir;
-	size_t			size;
-};
-
-struct ossp_cmd {
-	unsigned		magic;
-	enum ossp_opcode	opcode;
-	size_t			din_size;
-	size_t			dout_size;
-};
-
-struct ossp_reply {
-	unsigned		magic;
-	int			result;
-	size_t			dout_size;	/* <= cmd.data_in_size */
-};
-
-struct ossp_notify {
-	unsigned		magic;
-	enum ossp_notify_opcode opcode;
-};
-
-struct ossp_arg_size {
-	ssize_t			carg_size;
-	ssize_t			rarg_size;
-	unsigned		has_fd:1;
-};
-
-extern const struct ossp_arg_size ossp_arg_sizes[OSSP_NR_OPCODES];
-extern const char *ossp_cmd_str[OSSP_NR_OPCODES];
-extern const char *ossp_notify_str[OSSP_NR_NOTIFY_OPCODES];
-
-#endif /* _OSSP_H */
diff --git a/osspd.c b/osspd.c
deleted file mode 100644
index 37c9b35..0000000
--- a/osspd.c
+++ /dev/null
@@ -1,2295 +0,0 @@
-/*
- * osspd - OSS Proxy Daemon: emulate OSS device using CUSE
- *
- * Copyright (C) 2008-2010  SUSE Linux Products GmbH
- * Copyright (C) 2008-2010  Tejun Heo <tj@kernel.org>
- *
- * This file is released under the GPLv2.
- */
-
-#define FUSE_USE_VERSION 28
-#define _GNU_SOURCE
-
-#include <assert.h>
-#include <cuse_lowlevel.h>
-#include <fcntl.h>
-#include <fuse_opt.h>
-#include <libgen.h>
-#include <limits.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/epoll.h>
-#include <sys/socket.h>
-#include <sys/soundcard.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "ossp.h"
-#include "ossp-util.h"
-
-/*
- * MMAP support needs to be updated to the new fuse MMAP API.  Disable
- * it for the time being.
- */
-#warning mmap support disabled for now
-/* #define OSSP_MMAP */
-
-#define DFL_MIXER_NAME		"mixer"
-#define DFL_DSP_NAME		"dsp"
-#define DFL_ADSP_NAME		"adsp"
-#define STRFMT			"S[%u/%d]"
-#define STRID(os)		os->id, os->pid
-
-#define dbg1_os(os, fmt, args...)	dbg1(STRFMT" "fmt, STRID(os) , ##args)
-#define dbg0_os(os, fmt, args...)	dbg0(STRFMT" "fmt, STRID(os) , ##args)
-#define warn_os(os, fmt, args...)	warn(STRFMT" "fmt, STRID(os) , ##args)
-#define err_os(os, fmt, args...)	err(STRFMT" "fmt, STRID(os) , ##args)
-#define warn_ose(os, err, fmt, args...)	\
-	warn_e(err, STRFMT" "fmt, STRID(os) , ##args)
-#define err_ose(os, err, fmt, args...)	\
-	err_e(err, STRFMT" "fmt, STRID(os) , ##args)
-
-enum {
-	SNDRV_OSS_VERSION	= ((3<<16)|(8<<8)|(1<<4)|(0)),	/* 3.8.1a */
-	DFL_MIXER_MAJOR		= 14,
-	DFL_MIXER_MINOR		= 0,
-	DFL_DSP_MAJOR		= 14,
-	DFL_DSP_MINOR		= 3,
-	DFL_ADSP_MAJOR		= 14,
-	DFL_ADSP_MINOR		= 12,
-	DFL_MAX_STREAMS		= 128,
-	MIXER_PUT_DELAY		= 600,			/* 10 mins */
-	/* DSPS_MMAP_SIZE / 2 must be multiple of SHMLBA */
-	DSPS_MMAP_SIZE		= 2 * (512 << 10),	/* 512k for each dir */
-};
-
-struct ossp_uid_cnt {
-	struct list_head	link;
-	uid_t			uid;
-	unsigned		nr_os;
-};
-
-struct ossp_mixer {
-	pid_t			pgrp;
-	struct list_head	link;
-	struct list_head	delayed_put_link;
-	unsigned		refcnt;
-	/* the following two fields are protected by mixer_mutex */
-	int			vol[2][2];
-	int			modify_counter;
-	time_t			put_expires;
-};
-
-struct ossp_mixer_cmd {
-	struct ossp_mixer	*mixer;
-	struct ossp_mixer_arg	set;
-	int			out_dir;
-	int			rvol;
-};
-
-#define for_each_vol(i, j)						\
-	for (i = 0, j = 0; i < 2; j += i << 1, j++, i = j >> 1, j &= 1)
-
-struct ossp_stream {
-	unsigned		id;	/* stream ID */
-	struct list_head	link;
-	struct list_head	pgrp_link;
-	struct list_head	notify_link;
-	unsigned		refcnt;
-	pthread_mutex_t		cmd_mutex;
-	pthread_mutex_t		mmap_mutex;
-	struct fuse_pollhandle	*ph;
-
-	/* stream owner info */
-	pid_t			pid;
-	pid_t			pgrp;
-	uid_t			uid;
-	gid_t			gid;
-
-	/* slave info */
-	pid_t			slave_pid;
-	int			cmd_fd;
-	int			notify_tx;
-	int			notify_rx;
-
-	/* the following dead flag is set asynchronously, keep it separate. */
-	int			dead;
-
-	/* stream mixer state, protected by mixer_mutex */
-	int			mixer_pending;
-	int			vol[2][2];
-	int			vol_set[2][2];
-
-	off_t			mmap_off;
-	size_t			mmap_size;
-
-	struct ossp_uid_cnt	*ucnt;
-	struct fuse_session	*se;	/* associated fuse session */
-	struct ossp_mixer	*mixer;
-};
-
-struct ossp_dsp_stream {
-	struct ossp_stream	os;
-	unsigned		rw;
-	unsigned		mmapped;
-	int			nonblock;
-};
-
-#define os_to_dsps(_os)		container_of(_os, struct ossp_dsp_stream, os)
-
-static unsigned max_streams;
-static unsigned umax_streams;
-static unsigned hashtbl_size;
-static char dsp_slave_path[PATH_MAX];
-
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t mixer_mutex = PTHREAD_MUTEX_INITIALIZER;
-static unsigned long *os_id_bitmap;
-static unsigned nr_mixers;
-static struct list_head *mixer_tbl;	/* indexed by PGRP */
-static struct list_head *os_tbl;	/* indexed by ID */
-static struct list_head *os_pgrp_tbl;	/* indexed by PGRP */
-static struct list_head *os_notify_tbl;	/* indexed by notify fd */
-static LIST_HEAD(uid_cnt_list);
-static int notify_epfd;			/* epoll used to monitor notify fds */
-static pthread_t notify_poller_thread;
-static pthread_t slave_reaper_thread;
-static pthread_t mixer_delayed_put_thread;
-static pthread_t cuse_mixer_thread;
-static pthread_t cuse_adsp_thread;
-static pthread_cond_t notify_poller_kill_wait = PTHREAD_COND_INITIALIZER;
-static pthread_cond_t slave_reaper_wait = PTHREAD_COND_INITIALIZER;
-static LIST_HEAD(slave_corpse_list);
-static LIST_HEAD(mixer_delayed_put_head); /* delayed reference */
-static pthread_cond_t mixer_delayed_put_cond = PTHREAD_COND_INITIALIZER;
-
-static int init_wait_fd = -1;
-static int exit_on_idle;
-static struct fuse_session *mixer_se;
-static struct fuse_session *dsp_se;
-static struct fuse_session *adsp_se;
-
-static void put_os(struct ossp_stream *os);
-
-
-/***************************************************************************
- * Accessors
- */
-
-static struct list_head *mixer_tbl_head(pid_t pid)
-{
-	return &mixer_tbl[pid % hashtbl_size];
-}
-
-static struct list_head *os_tbl_head(uint64_t id)
-{
-	return &os_tbl[id % hashtbl_size];
-}
-
-static struct list_head *os_pgrp_tbl_head(pid_t pgrp)
-{
-	return &os_pgrp_tbl[pgrp % hashtbl_size];
-}
-
-static struct list_head *os_notify_tbl_head(int notify_rx)
-{
-	return &os_notify_tbl[notify_rx % hashtbl_size];
-}
-
-static struct ossp_mixer *find_mixer_locked(pid_t pgrp)
-{
-	struct ossp_mixer *mixer;
-
-	list_for_each_entry(mixer, mixer_tbl_head(pgrp), link)
-		if (mixer->pgrp == pgrp)
-			return mixer;
-	return NULL;
-}
-
-static struct ossp_mixer *find_mixer(pid_t pgrp)
-{
-	struct ossp_mixer *mixer;
-
-	pthread_mutex_lock(&mutex);
-	mixer = find_mixer_locked(pgrp);
-	pthread_mutex_unlock(&mutex);
-	return mixer;
-}
-
-static struct ossp_stream *find_os(unsigned id)
-{
-	struct ossp_stream *os, *found = NULL;
-
-	pthread_mutex_lock(&mutex);
-	list_for_each_entry(os, os_tbl_head(id), link)
-		if (os->id == id) {
-			found = os;
-			break;
-		}
-	pthread_mutex_unlock(&mutex);
-	return found;
-}
-
-static struct ossp_stream *find_os_by_notify_rx(int notify_rx)
-{
-	struct ossp_stream *os, *found = NULL;
-
-	pthread_mutex_lock(&mutex);
-	list_for_each_entry(os, os_notify_tbl_head(notify_rx), notify_link)
-		if (os->notify_rx == notify_rx) {
-			found = os;
-			break;
-		}
-	pthread_mutex_unlock(&mutex);
-	return found;
-}
-
-
-/***************************************************************************
- * Command and ioctl helpers
- */
-
-static ssize_t exec_cmd_intern(struct ossp_stream *os, enum ossp_opcode opcode,
-	const void *carg, size_t carg_size, const void *din, size_t din_size,
-	void *rarg, size_t rarg_size, void *dout, size_t *dout_sizep, int fd)
-{
-	size_t dout_size = dout_sizep ? *dout_sizep : 0;
-	struct ossp_cmd cmd = { .magic = OSSP_CMD_MAGIC, .opcode = opcode,
-				 .din_size = din_size,
-				 .dout_size = dout_size };
-	struct iovec iov = { &cmd, sizeof(cmd) };
-	struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
-	struct ossp_reply reply = { };
-	char cmsg_buf[CMSG_SPACE(sizeof(fd))];
-	char reason[512];
-	int rc;
-
-	if (os->dead)
-		return -EIO;
-
-	dbg1_os(os, "%s carg=%zu din=%zu rarg=%zu dout=%zu",
-		ossp_cmd_str[opcode], carg_size, din_size, rarg_size,
-		dout_size);
-
-	if (fd >= 0) {
-		struct cmsghdr *cmsg;
-
-		msg.msg_control = cmsg_buf;
-		msg.msg_controllen = sizeof(cmsg_buf);
-		cmsg = CMSG_FIRSTHDR(&msg);
-		cmsg->cmsg_level = SOL_SOCKET;
-		cmsg->cmsg_type = SCM_RIGHTS;
-		cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
-		*(int *)CMSG_DATA(cmsg) = fd;
-		msg.msg_controllen = cmsg->cmsg_len;
-	}
-
-	if (sendmsg(os->cmd_fd, &msg, 0) <= 0) {
-		rc = -errno;
-		snprintf(reason, sizeof(reason), "command sendmsg failed: %s",
-			 strerror(-rc));
-		goto fail;
-	}
-
-	if ((rc = write_fill(os->cmd_fd, carg, carg_size)) < 0 ||
-	    (rc = write_fill(os->cmd_fd, din, din_size)) < 0) {
-		snprintf(reason, sizeof(reason),
-			 "can't tranfer command argument and/or data: %s",
-			 strerror(-rc));
-		goto fail;
-	}
-	if ((rc = read_fill(os->cmd_fd, &reply, sizeof(reply))) < 0) {
-		snprintf(reason, sizeof(reason), "can't read reply: %s",
-			 strerror(-rc));
-		goto fail;
-	}
-
-	if (reply.magic != OSSP_REPLY_MAGIC) {
-		snprintf(reason, sizeof(reason),
-			 "reply magic mismatch %x != %x",
-			 reply.magic, OSSP_REPLY_MAGIC);
-		rc = -EINVAL;
-		goto fail;
-	}
-
-	if (reply.result < 0)
-		goto out_unlock;
-
-	if (reply.dout_size > dout_size) {
-		snprintf(reason, sizeof(reason),
-			 "data out size overflow %zu > %zu",
-			 reply.dout_size, dout_size);
-		rc = -EINVAL;
-		goto fail;
-	}
-
-	dout_size = reply.dout_size;
-	if (dout_sizep)
-		*dout_sizep = dout_size;
-
-	if ((rc = read_fill(os->cmd_fd, rarg, rarg_size)) < 0 ||
-	    (rc = read_fill(os->cmd_fd, dout, dout_size)) < 0) {
-		snprintf(reason, sizeof(reason), "can't read data out: %s",
-			 strerror(-rc));
-		goto fail;
-	}
-
-out_unlock:
-	dbg1_os(os, "  completed, result=%d dout=%zu",
-		reply.result, dout_size);
-	return reply.result;
-
-fail:
-	warn_os(os, "communication with slave failed (%s)", reason);
-	os->dead = 1;
-	return rc;
-}
-
-static ssize_t exec_cmd(struct ossp_stream *os, enum ossp_opcode opcode,
-	const void *carg, size_t carg_size, const void *din, size_t din_size,
-	void *rarg, size_t rarg_size, void *dout, size_t *dout_sizep, int fd)
-{
-	int is_mixer;
-	int i, j;
-	ssize_t ret, mret;
-
-	/* mixer command is handled exlicitly below */
-	is_mixer = opcode == OSSP_MIXER;
-	if (is_mixer) {
-		ret = -pthread_mutex_trylock(&os->cmd_mutex);
-		if (ret)
-			return ret;
-	} else {
-		pthread_mutex_lock(&os->cmd_mutex);
-
-		ret = exec_cmd_intern(os, opcode, carg, carg_size,
-				      din, din_size, rarg, rarg_size,
-				      dout, dout_sizep, fd);
-	}
-
-	/* lazy mixer handling */
-	pthread_mutex_lock(&mixer_mutex);
-
-	if (os->mixer_pending) {
-		struct ossp_mixer_arg marg;
-	repeat_mixer:
-		/* we have mixer command pending */
-		memcpy(marg.vol, os->vol_set, sizeof(os->vol_set));
-		memset(os->vol_set, -1, sizeof(os->vol_set));
-
-		pthread_mutex_unlock(&mixer_mutex);
-		mret = exec_cmd_intern(os, OSSP_MIXER, &marg, sizeof(marg),
-				       NULL, 0, &marg, sizeof(marg), NULL, NULL,
-				       -1);
-		pthread_mutex_lock(&mixer_mutex);
-
-		/* was there mixer set request while executing mixer command? */
-		for_each_vol(i, j)
-			if (os->vol_set[i][j] >= 0)
-				goto repeat_mixer;
-
-		/* update internal mixer state */
-		if (mret == 0) {
-			for_each_vol(i, j) {
-				if (marg.vol[i][j] >= 0) {
-					if (os->vol[i][j] != marg.vol[i][j])
-						os->mixer->modify_counter++;
-					os->vol[i][j] = marg.vol[i][j];
-				}
-			}
-		}
-		os->mixer_pending = 0;
-	}
-
-	pthread_mutex_unlock(&os->cmd_mutex);
-
-	/*
-	 * mixer mutex must be released after cmd_mutex so that
-	 * exec_mixer_cmd() can guarantee that mixer_pending flags
-	 * will be handled immediately or when the currently
-	 * in-progress command completes.
-	 */
-	pthread_mutex_unlock(&mixer_mutex);
-
-	return is_mixer ? mret : ret;
-}
-
-static ssize_t exec_simple_cmd(struct ossp_stream *os,
-			       enum ossp_opcode opcode, void *carg, void *rarg)
-{
-	return exec_cmd(os, opcode,
-			carg, ossp_arg_sizes[opcode].carg_size, NULL, 0,
-			rarg, ossp_arg_sizes[opcode].rarg_size, NULL, NULL, -1);
-}
-
-static int ioctl_prep_uarg(fuse_req_t req, void *in, size_t in_sz, void *out,
-			   size_t out_sz, void *uarg, const void *in_buf,
-			   size_t in_bufsz, size_t out_bufsz)
-{
-	struct iovec in_iov = { }, out_iov = { };
-	int retry = 0;
-
-	if (in) {
-		if (!in_bufsz) {
-			in_iov.iov_base = uarg;
-			in_iov.iov_len = in_sz;
-			retry = 1;
-		} else {
-			assert(in_bufsz == in_sz);
-			memcpy(in, in_buf, in_sz);
-		}
-	}
-
-	if (out) {
-		if (!out_bufsz) {
-			out_iov.iov_base = uarg;
-			out_iov.iov_len = out_sz;
-			retry = 1;
-		} else
-			assert(out_bufsz == out_sz);
-	}
-
-	if (retry)
-		fuse_reply_ioctl_retry(req, &in_iov, 1, &out_iov, 1);
-
-	return retry;
-}
-
-#define PREP_UARG(inp, outp) do {					\
-	if (ioctl_prep_uarg(req, (inp), sizeof(*(inp)),			\
-			    (outp), sizeof(*(outp)), uarg,		\
-			    in_buf, in_bufsz, out_bufsz))		\
-		return;							\
-} while (0)
-
-#define IOCTL_RETURN(result, outp) do {					\
-	if ((outp) != NULL)						\
-		fuse_reply_ioctl(req, result, (outp), sizeof(*(outp)));	\
-	else								\
-		fuse_reply_ioctl(req, result, NULL, 0);			\
-	return;								\
-} while (0)
-
-
-/***************************************************************************
- * Mixer implementation
- */
-
-static void put_mixer_real(struct ossp_mixer *mixer)
-{
-	if (!--mixer->refcnt) {
-		dbg0("DESTROY mixer(%d)", mixer->pgrp);
-		list_del_init(&mixer->link);
-		list_del_init(&mixer->delayed_put_link);
-		free(mixer);
-		nr_mixers--;
-
-		/*
-		 * If exit_on_idle, mixer for pgrp0 is touched during
-		 * init and each stream has mixer attached.  As mixers
-		 * are destroyed after they have been idle for
-		 * MIXER_PUT_DELAY seconds, we can use it for idle
-		 * detection.  Note that this might race with
-		 * concurrent open.  The race is inherent.
-		 */
-		if (exit_on_idle && !nr_mixers) {
-			info("idle, exiting");
-			exit(0);
-		}
-	}
-}
-
-static struct ossp_mixer *get_mixer(pid_t pgrp)
-{
-	struct ossp_mixer *mixer;
-
-	pthread_mutex_lock(&mutex);
-
-	/* is there a matching one? */
-	mixer = find_mixer_locked(pgrp);
-	if (mixer) {
-		if (list_empty(&mixer->delayed_put_link))
-			mixer->refcnt++;
-		else
-			list_del_init(&mixer->delayed_put_link);
-		goto out_unlock;
-	}
-
-	/* reap delayed put list if there are too many mixers */
-	while (nr_mixers > 2 * max_streams &&
-	       !list_empty(&mixer_delayed_put_head)) {
-		struct ossp_mixer *mixer =
-			list_first_entry(&mixer_delayed_put_head,
-					 struct ossp_mixer, delayed_put_link);
-
-		assert(mixer->refcnt == 1);
-		put_mixer_real(mixer);
-	}
-
-	/* create a new one */
-	mixer = calloc(1, sizeof(*mixer));
-	if (!mixer) {
-		warn("failed to allocate mixer for %d", pgrp);
-		mixer = NULL;
-		goto out_unlock;
-	}
-
-	mixer->pgrp = pgrp;
-	INIT_LIST_HEAD(&mixer->link);
-	INIT_LIST_HEAD(&mixer->delayed_put_link);
-	mixer->refcnt = 1;
-	memset(mixer->vol, -1, sizeof(mixer->vol));
-
-	list_add(&mixer->link, mixer_tbl_head(pgrp));
-	nr_mixers++;
-	dbg0("CREATE mixer(%d)", pgrp);
-
-out_unlock:
-	pthread_mutex_unlock(&mutex);
-	return mixer;
-}
-
-static void put_mixer(struct ossp_mixer *mixer)
-{
-	pthread_mutex_lock(&mutex);
-
-	if (mixer) {
-		if (mixer->refcnt == 1) {
-			struct timespec ts;
-
-			clock_gettime(CLOCK_REALTIME, &ts);
-			mixer->put_expires = ts.tv_sec + MIXER_PUT_DELAY;
-			list_add_tail(&mixer->delayed_put_link,
-				      &mixer_delayed_put_head);
-			pthread_cond_signal(&mixer_delayed_put_cond);
-		} else
-			put_mixer_real(mixer);
-	}
-
-	pthread_mutex_unlock(&mutex);
-}
-
-static void *mixer_delayed_put_worker(void *arg)
-{
-	struct ossp_mixer *mixer;
-	struct timespec ts;
-	time_t now;
-
-	pthread_mutex_lock(&mutex);
-again:
-	clock_gettime(CLOCK_REALTIME, &ts);
-	now = ts.tv_sec;
-
-	mixer = NULL;
-	while (!list_empty(&mixer_delayed_put_head)) {
-		mixer = list_first_entry(&mixer_delayed_put_head,
-					 struct ossp_mixer, delayed_put_link);
-
-		if (now <= mixer->put_expires)
-			break;
-
-		assert(mixer->refcnt == 1);
-		put_mixer_real(mixer);
-		mixer = NULL;
-	}
-
-	if (mixer) {
-		ts.tv_sec = mixer->put_expires + 1;
-		pthread_cond_timedwait(&mixer_delayed_put_cond, &mutex, &ts);
-	} else
-		pthread_cond_wait(&mixer_delayed_put_cond, &mutex);
-
-	goto again;
-}
-
-static void init_mixer_cmd(struct ossp_mixer_cmd *mxcmd,
-			   struct ossp_mixer *mixer)
-{
-	memset(mxcmd, 0, sizeof(*mxcmd));
-	memset(&mxcmd->set.vol, -1, sizeof(mxcmd->set.vol));
-	mxcmd->mixer = mixer;
-	mxcmd->out_dir = -1;
-}
-
-static int exec_mixer_cmd(struct ossp_mixer_cmd *mxcmd, struct ossp_stream *os)
-{
-	int i, j, rc;
-
-	/*
-	 * Set pending flags before trying to execute mixer command.
-	 * Combined with lock release order in exec_cmd(), this
-	 * guarantees that the mixer command will be executed
-	 * immediately or when the current command completes.
-	 */
-	pthread_mutex_lock(&mixer_mutex);
-	os->mixer_pending = 1;
-	for_each_vol(i, j)
-		if (mxcmd->set.vol[i][j] >= 0)
-			os->vol_set[i][j] = mxcmd->set.vol[i][j];
-	pthread_mutex_unlock(&mixer_mutex);
-
-	rc = exec_simple_cmd(os, OSSP_MIXER, NULL, NULL);
-	if (rc >= 0) {
-		dbg0_os(os, "volume set=%d/%d:%d/%d get=%d/%d:%d/%d",
-			mxcmd->set.vol[PLAY][LEFT], mxcmd->set.vol[PLAY][RIGHT],
-			mxcmd->set.vol[REC][LEFT], mxcmd->set.vol[REC][RIGHT],
-			os->vol[PLAY][LEFT], os->vol[PLAY][RIGHT],
-			os->vol[REC][LEFT], os->vol[REC][RIGHT]);
-	} else if (rc != -EBUSY)
-		warn_ose(os, rc, "mixer command failed");
-
-	return rc;
-}
-
-static void finish_mixer_cmd(struct ossp_mixer_cmd *mxcmd)
-{
-	struct ossp_mixer *mixer = mxcmd->mixer;
-	struct ossp_stream *os;
-	int dir = mxcmd->out_dir;
-	int vol[2][2] = { };
-	int cnt[2][2] = { };
-	int i, j;
-
-	pthread_mutex_lock(&mixer_mutex);
-
-	/* get volume of all streams attached to this mixer */
-	pthread_mutex_lock(&mutex);
-	list_for_each_entry(os, os_pgrp_tbl_head(mixer->pgrp), pgrp_link) {
-		if (os->pgrp != mixer->pgrp)
-			continue;
-		for_each_vol(i, j) {
-			if (os->vol[i][j] < 0)
-				continue;
-			vol[i][j] += os->vol[i][j];
-			cnt[i][j]++;
-		}
-	}
-	pthread_mutex_unlock(&mutex);
-
-	/* calculate the summary volume values */
-	for_each_vol(i, j) {
-		if (mxcmd->set.vol[i][j] >= 0)
-			vol[i][j] = mxcmd->set.vol[i][j];
-		else if (cnt[i][j])
-			vol[i][j] = vol[i][j] / cnt[i][j];
-		else if (mixer->vol[i][j] >= 0)
-			vol[i][j] = mixer->vol[i][j];
-		else
-			vol[i][j] = 100;
-
-		vol[i][j] = min(max(0, vol[i][j]), 100);
-	}
-
-	if (dir >= 0)
-		mxcmd->rvol = vol[dir][LEFT] | (vol[dir][RIGHT] << 8);
-
-	pthread_mutex_unlock(&mixer_mutex);
-}
-
-static void mixer_simple_ioctl(fuse_req_t req, struct ossp_mixer *mixer,
-			       unsigned cmd, void *uarg, const void *in_buf,
-			       size_t in_bufsz, size_t out_bufsz,
-			       int *not_minep)
-{
-	const char *id = "OSS Proxy", *name = "Mixer";
-	int i;
-
-	switch (cmd) {
-	case SOUND_MIXER_INFO: {
-		struct mixer_info info = { };
-
-		PREP_UARG(NULL, &info);
-		strncpy(info.id, id, sizeof(info.id) - 1);
-		strncpy(info.name, name, sizeof(info.name) - 1);
-		info.modify_counter = mixer->modify_counter;
-		IOCTL_RETURN(0, &info);
-	}
-
-	case SOUND_OLD_MIXER_INFO: {
-		struct _old_mixer_info info = { };
-
-		PREP_UARG(NULL, &info);
-		strncpy(info.id, id, sizeof(info.id) - 1);
-		strncpy(info.name, name, sizeof(info.name) - 1);
-		IOCTL_RETURN(0, &info);
-	}
-
-	case OSS_GETVERSION:
-		i = SNDRV_OSS_VERSION;
-		goto puti;
-	case SOUND_MIXER_READ_DEVMASK:
-	case SOUND_MIXER_READ_STEREODEVS:
-		i = SOUND_MASK_PCM | SOUND_MASK_IGAIN;
-		goto puti;
-	case SOUND_MIXER_READ_CAPS:
-		i = SOUND_CAP_EXCL_INPUT;
-		goto puti;
-	case SOUND_MIXER_READ_RECMASK:
-	case SOUND_MIXER_READ_RECSRC:
-		i = SOUND_MASK_IGAIN;
-		goto puti;
-	puti:
-		PREP_UARG(NULL, &i);
-		IOCTL_RETURN(0, &i);
-
-	case SOUND_MIXER_WRITE_RECSRC:
-		IOCTL_RETURN(0, NULL);
-
-	default:
-		*not_minep = 1;
-		return;
-	}
-	assert(0);
-}
-
-static void mixer_do_ioctl(fuse_req_t req, struct ossp_mixer *mixer,
-			   unsigned cmd, void *uarg, const void *in_buf,
-			   size_t in_bufsz, size_t out_bufsz)
-{
-	struct ossp_mixer_cmd mxcmd;
-	struct ossp_stream *os, **osa;
-	int not_mine = 0;
-	int slot = cmd & 0xff, dir;
-	int nr_os;
-	int i, rc;
-
-	mixer_simple_ioctl(req, mixer, cmd, uarg, in_buf, in_bufsz, out_bufsz,
-			   &not_mine);
-	if (!not_mine)
-		return;
-
-	rc = -ENXIO;
-	if (!(cmd & (SIOC_IN | SIOC_OUT)))
-		goto err;
-
-	/*
-	 * Okay, it's not one of the easy ones.  Build mxcmd for
-	 * actual volume control.
-	 */
-	if (cmd & SIOC_IN)
-		PREP_UARG(&i, &i);
-	else
-		PREP_UARG(NULL, &i);
-
-	switch (slot) {
-	case SOUND_MIXER_PCM:
-		dir = PLAY;
-		break;
-	case SOUND_MIXER_IGAIN:
-		dir = REC;
-		break;
-	default:
-		i = 0;
-		IOCTL_RETURN(0, &i);
-	}
-
-	init_mixer_cmd(&mxcmd, mixer);
-
-	if (cmd & SIOC_IN) {
-		unsigned l, r;
-
-		rc = -EINVAL;
-		l = i & 0xff;
-		r = (i >> 8) & 0xff;
-		if (l > 100 || r > 100)
-			goto err;
-
-		mixer->vol[dir][LEFT] = mxcmd.set.vol[dir][LEFT] = l;
-		mixer->vol[dir][RIGHT] = mxcmd.set.vol[dir][RIGHT] = r;
-	}
-	mxcmd.out_dir = dir;
-
-	/*
-	 * Apply volume conrol
-	 */
-	/* acquire target streams */
-	pthread_mutex_lock(&mutex);
-	osa = calloc(max_streams, sizeof(osa[0]));
-	if (!osa) {
-		pthread_mutex_unlock(&mutex);
-		rc = -ENOMEM;
-		goto err;
-	}
-
-	nr_os = 0;
-	list_for_each_entry(os, os_pgrp_tbl_head(mixer->pgrp), pgrp_link) {
-		if (os->pgrp == mixer->pgrp) {
-			osa[nr_os++] = os;
-			os->refcnt++;
-		}
- 	}
-
-	pthread_mutex_unlock(&mutex);
-
-	/* execute mxcmd for each stream and put it */
-	for (i = 0; i < nr_os; i++) {
-		exec_mixer_cmd(&mxcmd, osa[i]);
-		put_os(osa[i]);
-	}
-
-	finish_mixer_cmd(&mxcmd);
-	free(osa);
-
-	IOCTL_RETURN(0, out_bufsz ? &mxcmd.rvol : NULL);
-
-err:
-	fuse_reply_err(req, -rc);
-}
-
-static void mixer_open(fuse_req_t req, struct fuse_file_info *fi)
-{
-	pid_t pid = fuse_req_ctx(req)->pid, pgrp;
-	struct ossp_mixer *mixer;
-	int rc;
-
-	rc = get_proc_self_info(pid, &pgrp, NULL, 0);
-	if (rc) {
-		err_e(rc, "get_proc_self_info(%d) failed", pid);
-		fuse_reply_err(req, -rc);
-		return;
-	}
-
-	mixer = get_mixer(pgrp);
-	fi->fh = pgrp;
-
-	if (mixer)
-		fuse_reply_open(req, fi);
-	else
-		fuse_reply_err(req, ENOMEM);
-}
-
-static void mixer_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
-			struct fuse_file_info *fi, unsigned int flags,
-			const void *in_buf, size_t in_bufsz, size_t out_bufsz)
-{
-	struct ossp_mixer *mixer;
-
-	mixer = find_mixer(fi->fh);
-	if (!mixer) {
-		fuse_reply_err(req, EBADF);
-		return;
-	}
-
-	mixer_do_ioctl(req, mixer, signed_cmd, uarg, in_buf, in_bufsz,
-		       out_bufsz);
-}
-
-static void mixer_release(fuse_req_t req, struct fuse_file_info *fi)
-{
-	struct ossp_mixer *mixer;
-
-	mixer = find_mixer(fi->fh);
-	if (mixer) {
-		put_mixer(mixer);
-		fuse_reply_err(req, 0);
-	} else
-		fuse_reply_err(req, EBADF);
-}
-
-
-/***************************************************************************
- * Stream implementation
- */
-
-static int alloc_os(size_t stream_size, size_t mmap_size, pid_t pid, uid_t pgrp,
-		    uid_t uid, gid_t gid, int cmd_sock,
-		    const int *notify, struct fuse_session *se,
-		    struct ossp_stream **osp)
-{
-	struct ossp_uid_cnt *tmp_ucnt, *ucnt = NULL;
-	struct ossp_stream *os;
-	int rc;
-
-	assert(stream_size >= sizeof(struct ossp_stream));
-	os = calloc(1, stream_size);
-	if (!os)
-		return -ENOMEM;
-
-	INIT_LIST_HEAD(&os->link);
-	INIT_LIST_HEAD(&os->pgrp_link);
-	INIT_LIST_HEAD(&os->notify_link);
-	os->refcnt = 1;
-
-	rc = -pthread_mutex_init(&os->cmd_mutex, NULL);
-	if (rc)
-		goto err_free;
-
-	rc = -pthread_mutex_init(&os->mmap_mutex, NULL);
-	if (rc)
-		goto err_destroy_cmd_mutex;
-
-	pthread_mutex_lock(&mutex);
-
-	list_for_each_entry(tmp_ucnt, &uid_cnt_list, link)
-		if (tmp_ucnt->uid == uid) {
-			ucnt = tmp_ucnt;
-			break;
-		}
-	if (!ucnt) {
-		rc = -ENOMEM;
-		ucnt = calloc(1, sizeof(*ucnt));
-		if (!ucnt)
-			goto err_unlock;
-		ucnt->uid = uid;
-		list_add(&ucnt->link, &uid_cnt_list);
-	}
-
-	rc = -EBUSY;
-	if (ucnt->nr_os + 1 > umax_streams)
-		goto err_unlock;
-
-	/* everything looks fine, allocate id and init stream */
-	rc = -EBUSY;
-	os->id = find_next_zero_bit(os_id_bitmap, max_streams, 0);
-	if (os->id >= max_streams)
-		goto err_unlock;
-	__set_bit(os->id, os_id_bitmap);
-
-	os->cmd_fd = cmd_sock;
-	os->notify_tx = notify[1];
-	os->notify_rx = notify[0];
-	os->pid = pid;
-	os->pgrp = pgrp;
-	os->uid = uid;
-	os->gid = gid;
-	if (mmap_size) {
-		os->mmap_off = os->id * mmap_size;
-		os->mmap_size = mmap_size;
-	}
-	os->ucnt = ucnt;
-	os->se = se;
-
-	memset(os->vol, -1, sizeof(os->vol));
-	memset(os->vol_set, -1, sizeof(os->vol));
-
-	list_add(&os->link, os_tbl_head(os->id));
-	list_add(&os->pgrp_link, os_pgrp_tbl_head(os->pgrp));
-
-	ucnt->nr_os++;
-	*osp = os;
-	pthread_mutex_unlock(&mutex);
-	return 0;
-
-err_unlock:
-	pthread_mutex_unlock(&mutex);
-	pthread_mutex_destroy(&os->mmap_mutex);
-err_destroy_cmd_mutex:
-	pthread_mutex_destroy(&os->cmd_mutex);
-err_free:
-	free(os);
-	return rc;
-}
-
-static void shutdown_notification(struct ossp_stream *os)
-{
-	struct ossp_notify obituary = { .magic = OSSP_NOTIFY_MAGIC,
-					.opcode = OSSP_NOTIFY_OBITUARY };
-	ssize_t ret;
-
-	/*
-	 * Shutdown notification for this stream.  We politely ask
-	 * notify_poller to shut the receive side down to avoid racing
-	 * with it.
-	 */
-	while (os->notify_rx >= 0) {
-		ret = write(os->notify_tx, &obituary, sizeof(obituary));
-		if (ret <= 0) {
-			if (ret == 0)
-				warn_os(os, "unexpected EOF on notify_tx");
-			else if (errno != EPIPE)
-				warn_ose(os, -errno,
-					 "unexpected error on notify_tx");
-			close(os->notify_rx);
-			os->notify_rx = -1;
-			break;
-		}
-
-		if (ret != sizeof(obituary))
-			warn_os(os, "short transfer on notify_tx");
-		pthread_cond_wait(&notify_poller_kill_wait, &mutex);
-	}
-}
-
-static void put_os(struct ossp_stream *os)
-{
-	if (!os)
-		return;
-
-	pthread_mutex_lock(&mutex);
-
-	assert(os->refcnt);
-	if (--os->refcnt) {
-		pthread_mutex_unlock(&mutex);
-		return;
-	}
-
-	os->dead = 1;
-	shutdown_notification(os);
-
-	dbg0_os(os, "DESTROY");
-
-	list_del_init(&os->link);
-	list_del_init(&os->pgrp_link);
-	list_del_init(&os->notify_link);
-	os->ucnt->nr_os--;
-
-	pthread_mutex_unlock(&mutex);
-
-	close(os->cmd_fd);
-	close(os->notify_tx);
-	put_mixer(os->mixer);
-	pthread_mutex_destroy(&os->cmd_mutex);
-	pthread_mutex_destroy(&os->mmap_mutex);
-
-	pthread_mutex_lock(&mutex);
-	dbg1_os(os, "stream dead, requesting reaping");
-	list_add_tail(&os->link, &slave_corpse_list);
-	pthread_cond_signal(&slave_reaper_wait);
-	pthread_mutex_unlock(&mutex);
-}
-
-static void set_extra_env(pid_t pid)
-{
-	char procenviron[32];
-	const int step = 1024;
-	char *data = malloc(step + 1);
-	int ofs = 0;
-	int fd;
-	int ret;
-
-	if (!data)
-		return;
-
-	sprintf(procenviron, "/proc/%d/environ", pid);
-	fd = open(procenviron, O_RDONLY);
-	if (fd < 0)
-		return;
-
-	/*
-	 * There should really be a 'read whole file to a newly allocated
-	 * buffer' function.
-	 */
-	while ((ret = read(fd, data + ofs, step)) > 0) {
-		char *newdata;
-		ofs += ret;
-		newdata = realloc(data, ofs + step + 1);
-		if (!newdata) {
-			ret = -1;
-			break;
-		}
-		data = newdata;
-	}
-	if (ret == 0) {
-		char *ptr = data;
-		/* Append the extra 0 for end condition */
-		data[ofs] = 0;
-
-		while ((ret = strlen(ptr)) > 0) {
-			/*
-			 * Copy all PULSE variables and DISPLAY so that
-			 * ssh -X remotehost 'mplayer -ao oss' will work
-			 */
-			if (!strncmp(ptr, "DISPLAY=", 8) ||
-			    !strncmp(ptr, "PULSE_", 6))
-				putenv(ptr);
-			ptr += ret + 1;
-		}
-	}
-
-	free(data);
-	close(fd);
-}
-
-static int create_os(const char *slave_path,
-		     size_t stream_size, size_t mmap_size,
-		     pid_t pid, pid_t pgrp, uid_t uid, gid_t gid,
-		     struct fuse_session *se, struct ossp_stream **osp)
-{
-	static pthread_mutex_t create_mutex = PTHREAD_MUTEX_INITIALIZER;
-	int cmd_sock[2] = { -1, -1 };
-	int notify_sock[2] = { -1, -1 };
-	struct ossp_stream *os = NULL;
-	struct epoll_event ev = { };
-	int i, rc;
-
-	/*
-	 * Only one thread can be creating a stream.  This is to avoid
-	 * leaking unwanted fds into slaves.
-	 */
-	pthread_mutex_lock(&create_mutex);
-
-	/* prepare communication channels */
-	if (socketpair(AF_UNIX, SOCK_STREAM, 0, cmd_sock) ||
-	    socketpair(AF_UNIX, SOCK_STREAM, 0, notify_sock)) {
-		rc = -errno;
-		warn_e(rc, "failed to create slave command channel");
-		goto close_all;
-	}
-
-	if (fcntl(notify_sock[0], F_SETFL, O_NONBLOCK) < 0) {
-		rc = -errno;
-		warn_e(rc, "failed to set NONBLOCK on notify sock");
-		goto close_all;
-	}
-
-	/*
-	 * Alloc stream which will be responsible for all server side
-	 * resources from now on.
-	 */
-	rc = alloc_os(stream_size, mmap_size, pid, pgrp, uid, gid, cmd_sock[0],
-		      notify_sock, se, &os);
-	if (rc) {
-		warn_e(rc, "failed to allocate stream for %d", pid);
-		goto close_all;
-	}
-
-	rc = -ENOMEM;
-	os->mixer = get_mixer(pgrp);
-	if (!os->mixer)
-		goto put_os;
-
-	/*
-	 * Register notification.  If successful, notify_poller has
-	 * custody of notify_rx fd.
-	 */
-	pthread_mutex_lock(&mutex);
-	list_add(&os->notify_link, os_notify_tbl_head(os->notify_rx));
-	pthread_mutex_unlock(&mutex);
-
-	ev.events = EPOLLIN;
-	ev.data.fd = notify_sock[0];
-	if (epoll_ctl(notify_epfd, EPOLL_CTL_ADD, notify_sock[0], &ev)) {
-		/*
-		 * Without poller watching this notify sock, poller
-		 * shutdown sequence in shutdown_notification() can't
-		 * be used.  Kill notification rx manually.
-		 */
-		rc = -errno;
-		warn_ose(os, rc, "failed to add notify epoll");
-		close(os->notify_rx);
-		os->notify_rx = -1;
-		goto put_os;
-	}
-
-	/* start slave */
-	os->slave_pid = fork();
-	if (os->slave_pid < 0) {
-		rc = -errno;
-		warn_ose(os, rc, "failed to fork slave");
-		goto put_os;
-	}
-
-	if (os->slave_pid == 0) {
-		/* child */
-		char id_str[2][16], fd_str[3][16];
-		char mmap_off_str[32], mmap_size_str[32];
-		char log_str[16], slave_path_copy[PATH_MAX];
-		char *argv[] = { slave_path_copy, "-u", id_str[0],
-				 "-g", id_str[1], "-c", fd_str[0],
-				 "-n", fd_str[1], "-m", fd_str[2],
-				 "-o", mmap_off_str, "-s", mmap_size_str,
-				 "-l", log_str, NULL, NULL };
-		struct passwd *pwd;
-
-		/* drop stuff we don't need */
-		if (close(cmd_sock[0]) || close(notify_sock[0]))
-			fatal_e(-errno, "failed to close server pipe fds");
-
-#ifdef OSSP_MMAP
-		if (!mmap_size)
-			close(fuse_mmap_fd(se));
-#endif
-
-		clearenv();
-		pwd = getpwuid(os->uid);
-		if (pwd) {
-			setenv("LOGNAME", pwd->pw_name, 1);
-			setenv("USER", pwd->pw_name, 1);
-			setenv("HOME", pwd->pw_dir, 1);
-		}
-		/* Set extra environment variables from the caller */
-		set_extra_env(pid);
-
-		/* prep and exec */
-		slave_path_copy[sizeof(slave_path_copy) - 1] = '\0';
-		strncpy(slave_path_copy, slave_path, sizeof(slave_path_copy) - 1);
-		if (slave_path_copy[sizeof(slave_path_copy) - 1] != '\0') {
-			rc = -errno;
-			err_ose(os, rc, "slave path too long");
-			goto child_fail;
-		}
-
-		snprintf(id_str[0], sizeof(id_str[0]), "%d", os->uid);
-		snprintf(id_str[1], sizeof(id_str[0]), "%d", os->gid);
-		snprintf(fd_str[0], sizeof(fd_str[0]), "%d", cmd_sock[1]);
-		snprintf(fd_str[1], sizeof(fd_str[1]), "%d", notify_sock[1]);
-		snprintf(fd_str[2], sizeof(fd_str[2]), "%d",
-#ifdef OSSP_MMAP
-			 mmap_size ? fuse_mmap_fd(se) :
-#endif
-			 -1);
-		snprintf(mmap_off_str, sizeof(mmap_off_str), "0x%llx",
-			 (unsigned long long)os->mmap_off);
-		snprintf(mmap_size_str, sizeof(mmap_size_str), "0x%zx",
-			 mmap_size);
-		snprintf(log_str, sizeof(log_str), "%d", ossp_log_level);
-		if (ossp_log_timestamp)
-			argv[ARRAY_SIZE(argv) - 2] = "-t";
-
-		execv(slave_path, argv);
-		rc = -errno;
-		err_ose(os, rc, "execv failed for <%d>", pid);
-	child_fail:
-		_exit(1);
-	}
-
-	/* turn on CLOEXEC on all server side fds */
-	if (fcntl(os->cmd_fd, F_SETFD, FD_CLOEXEC) < 0 ||
-	    fcntl(os->notify_tx, F_SETFD, FD_CLOEXEC) < 0 ||
-	    fcntl(os->notify_rx, F_SETFD, FD_CLOEXEC) < 0) {
-		rc = -errno;
-		err_ose(os, rc, "failed to set CLOEXEC on server side fds");
-		goto put_os;
-	}
-
-	dbg0_os(os, "CREATE slave=%d %s", os->slave_pid, slave_path);
-	dbg0_os(os, "  client=%d cmd=%d:%d notify=%d:%d mmap=%d:0x%llx:%zu",
-		pid, cmd_sock[0], cmd_sock[1], notify_sock[0], notify_sock[1],
-#ifdef OSSP_MMAP
-		os->mmap_size ? fuse_mmap_fd(se) :
-#endif
-		-1,
-		(unsigned long long)os->mmap_off, os->mmap_size);
-
-	*osp = os;
-	rc = 0;
-	goto close_client_fds;
-
-put_os:
-	put_os(os);
-close_client_fds:
-	close(cmd_sock[1]);
-	pthread_mutex_unlock(&create_mutex);
-	return rc;
-
-close_all:
-	for (i = 0; i < 2; i++) {
-		close(cmd_sock[i]);
-		close(notify_sock[i]);
-	}
-	pthread_mutex_unlock(&create_mutex);
-	return rc;
-}
-
-static void dsp_open_common(fuse_req_t req, struct fuse_file_info *fi,
-			    struct fuse_session *se)
-{
-	const struct fuse_ctx *fuse_ctx = fuse_req_ctx(req);
-	struct ossp_dsp_open_arg arg = { };
-	struct ossp_stream *os = NULL;
-	struct ossp_mixer *mixer;
-	struct ossp_dsp_stream *dsps;
-	struct ossp_mixer_cmd mxcmd;
-	pid_t pgrp;
-	ssize_t ret;
-
-	ret = get_proc_self_info(fuse_ctx->pid, &pgrp, NULL, 0);
-	if (ret) {
-		err_e(ret, "get_proc_self_info(%d) failed", fuse_ctx->pid);
-		goto err;
-	}
-
-	ret = create_os(dsp_slave_path, sizeof(*dsps), DSPS_MMAP_SIZE,
-			fuse_ctx->pid, pgrp, fuse_ctx->uid, fuse_ctx->gid,
-			se, &os);
-	if (ret)
-		goto err;
-	dsps = os_to_dsps(os);
-	mixer = os->mixer;
-
-	switch (fi->flags & O_ACCMODE) {
-	case O_WRONLY:
-		dsps->rw |= 1 << PLAY;
-		break;
-	case O_RDONLY:
-		dsps->rw |= 1 << REC;
-		break;
-	case O_RDWR:
-		dsps->rw |= (1 << PLAY) | (1 << REC);
-		break;
-	default:
-		assert(0);
-	}
-
-	arg.flags = fi->flags;
-	arg.opener_pid = os->pid;
-	ret = exec_simple_cmd(&dsps->os, OSSP_DSP_OPEN, &arg, NULL);
-	if (ret < 0) {
-		put_os(os);
-		goto err;
-	}
-
-	memcpy(os->vol, mixer->vol, sizeof(os->vol));
-	if (os->vol[PLAY][0] >= 0 || os->vol[REC][0] >= 0) {
-		init_mixer_cmd(&mxcmd, mixer);
-		memcpy(mxcmd.set.vol, os->vol, sizeof(os->vol));
-		exec_mixer_cmd(&mxcmd, os);
-		finish_mixer_cmd(&mxcmd);
-	}
-
-	fi->direct_io = 1;
-	fi->nonseekable = 1;
-	fi->fh = os->id;
-
-	fuse_reply_open(req, fi);
-	return;
-
-err:
-	fuse_reply_err(req, -ret);
-}
-
-static void dsp_open(fuse_req_t req, struct fuse_file_info *fi)
-{
-	dsp_open_common(req, fi, dsp_se);
-}
-
-static void adsp_open(fuse_req_t req, struct fuse_file_info *fi)
-{
-	dsp_open_common(req, fi, adsp_se);
-}
-
-static void dsp_release(fuse_req_t req, struct fuse_file_info *fi)
-{
-	struct ossp_stream *os;
-
-	os = find_os(fi->fh);
-	if (os) {
-		put_os(os);
-		fuse_reply_err(req, 0);
-	} else
-		fuse_reply_err(req, EBADF);
-}
-
-static void dsp_read(fuse_req_t req, size_t size, off_t off,
-		     struct fuse_file_info *fi)
-{
-	struct ossp_dsp_rw_arg arg = { };
-	struct ossp_stream *os;
-	struct ossp_dsp_stream *dsps;
-	void *buf = NULL;
-	ssize_t ret;
-
-	ret = -EBADF;
-	os = find_os(fi->fh);
-	if (!os)
-		goto out;
-	dsps = os_to_dsps(os);
-
-	ret = -EINVAL;
-	if (!(dsps->rw & (1 << REC)))
-		goto out;
-
-	ret = -ENXIO;
-	if (dsps->mmapped)
-		goto out;
-
-	ret = -ENOMEM;
-	buf = malloc(size);
-	if (!buf)
-		goto out;
-
-	arg.nonblock = (fi->flags & O_NONBLOCK) || dsps->nonblock;
-
-	ret = exec_cmd(os, OSSP_DSP_READ, &arg, sizeof(arg),
-		       NULL, 0, NULL, 0, buf, &size, -1);
-out:
-	if (ret >= 0)
-		fuse_reply_buf(req, buf, size);
-	else
-		fuse_reply_err(req, -ret);
-
-	free(buf);
-}
-
-static void dsp_write(fuse_req_t req, const char *buf, size_t size, off_t off,
-		      struct fuse_file_info *fi)
-{
-	struct ossp_dsp_rw_arg arg = { };
-	struct ossp_stream *os;
-	struct ossp_dsp_stream *dsps;
-	ssize_t ret;
-
-	ret = -EBADF;
-	os = find_os(fi->fh);
-	if (!os)
-		goto out;
-	dsps = os_to_dsps(os);
-
-	ret = -EINVAL;
-	if (!(dsps->rw & (1 << PLAY)))
-		goto out;
-
-	ret = -ENXIO;
-	if (dsps->mmapped)
-		goto out;
-
-	arg.nonblock = (fi->flags & O_NONBLOCK) || dsps->nonblock;
-
-	ret = exec_cmd(os, OSSP_DSP_WRITE, &arg, sizeof(arg),
-		       buf, size, NULL, 0, NULL, NULL, -1);
-out:
-	if (ret >= 0)
-		fuse_reply_write(req, ret);
-	else
-		fuse_reply_err(req, -ret);
-}
-
-static void dsp_poll(fuse_req_t req, struct fuse_file_info *fi,
-		     struct fuse_pollhandle *ph)
-{
-	int notify = ph != NULL;
-	unsigned revents = 0;
-	struct ossp_stream *os;
-	ssize_t ret;
-
-	ret = -EBADF;
-	os = find_os(fi->fh);
-	if (!os)
-		goto out;
-
-	if (ph) {
-		pthread_mutex_lock(&mutex);
-		if (os->ph)
-			fuse_pollhandle_destroy(os->ph);
-		os->ph = ph;
-		pthread_mutex_unlock(&mutex);
-	}
-
-	ret = exec_simple_cmd(os, OSSP_DSP_POLL, &notify, &revents);
-out:
-	if (ret >= 0)
-		fuse_reply_poll(req, revents);
-	else
-		fuse_reply_err(req, -ret);
-}
-
-static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg,
-		      struct fuse_file_info *fi, unsigned int flags,
-		      const void *in_buf, size_t in_bufsz, size_t out_bufsz)
-{
-	/* some ioctl constants are long and has the highest bit set */
-	unsigned cmd = signed_cmd;
-	struct ossp_stream *os;
-	struct ossp_dsp_stream *dsps;
-	enum ossp_opcode op;
-	ssize_t ret;
-	int i;
-
-	ret = -EBADF;
-	os = find_os(fi->fh);
-	if (!os)
-		goto err;
-	dsps = os_to_dsps(os);
-
-	/* mixer commands are allowed on DSP devices */
-	if (((cmd >> 8) & 0xff) == 'M') {
-		mixer_do_ioctl(req, os->mixer, cmd, uarg, in_buf, in_bufsz,
-			       out_bufsz);
-		return;
-	}
-
-	/* and the rest */
-	switch (cmd) {
-	case OSS_GETVERSION:
-		i = SNDRV_OSS_VERSION;
-		PREP_UARG(NULL, &i);
-		IOCTL_RETURN(0, &i);
-
-	case SNDCTL_DSP_GETCAPS:
-		i = DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER |
-#ifdef OSSP_MMAP
-			DSP_CAP_MMAP |
-#endif
-			DSP_CAP_MULTI;
-		PREP_UARG(NULL, &i);
-		IOCTL_RETURN(0, &i);
-
-	case SNDCTL_DSP_NONBLOCK:
-		dsps->nonblock = 1;
-		ret = 0;
-		IOCTL_RETURN(0, NULL);
-
-	case SNDCTL_DSP_RESET:		op = OSSP_DSP_RESET;		goto nd;
-	case SNDCTL_DSP_SYNC:		op = OSSP_DSP_SYNC;		goto nd;
-	case SNDCTL_DSP_POST:		op = OSSP_DSP_POST;		goto nd;
-	nd:
-		ret = exec_simple_cmd(&dsps->os, op, NULL, NULL);
-		if (ret)
-			goto err;
-		IOCTL_RETURN(0, NULL);
-
-	case SOUND_PCM_READ_RATE:	op = OSSP_DSP_GET_RATE;		goto ri;
-	case SOUND_PCM_READ_BITS:	op = OSSP_DSP_GET_FORMAT;	goto ri;
-	case SOUND_PCM_READ_CHANNELS:	op = OSSP_DSP_GET_CHANNELS;	goto ri;
-	case SNDCTL_DSP_GETBLKSIZE:	op = OSSP_DSP_GET_BLKSIZE;	goto ri;
-	case SNDCTL_DSP_GETFMTS:	op = OSSP_DSP_GET_FORMATS;	goto ri;
-	case SNDCTL_DSP_GETTRIGGER:	op = OSSP_DSP_GET_TRIGGER;	goto ri;
-	ri:
-		PREP_UARG(NULL, &i);
-		ret = exec_simple_cmd(&dsps->os, op, NULL, &i);
-		if (ret)
-			goto err;
-		IOCTL_RETURN(0, &i);
-
-	case SNDCTL_DSP_SPEED:		op = OSSP_DSP_SET_RATE;		goto wi;
-	case SNDCTL_DSP_SETFMT:		op = OSSP_DSP_SET_FORMAT;	goto wi;
-	case SNDCTL_DSP_CHANNELS:	op = OSSP_DSP_SET_CHANNELS;	goto wi;
-	case SNDCTL_DSP_SUBDIVIDE:	op = OSSP_DSP_SET_SUBDIVISION;	goto wi;
-	wi:
-		PREP_UARG(&i, &i);
-		ret = exec_simple_cmd(&dsps->os, op, &i, &i);
-		if (ret)
-			goto err;
-		IOCTL_RETURN(0, &i);
-
-	case SNDCTL_DSP_STEREO:
-		PREP_UARG(NULL, &i);
-		i = 2;
-		ret = exec_simple_cmd(&dsps->os, OSSP_DSP_SET_CHANNELS, &i, &i);
-		i--;
-		if (ret)
-			goto err;
-		IOCTL_RETURN(0, &i);
-
-	case SNDCTL_DSP_SETFRAGMENT:
-		PREP_UARG(&i, NULL);
-		ret = exec_simple_cmd(&dsps->os,
-				      OSSP_DSP_SET_FRAGMENT, &i, NULL);
-		if (ret)
-			goto err;
-		IOCTL_RETURN(0, NULL);
-
-	case SNDCTL_DSP_SETTRIGGER:
-		PREP_UARG(&i, NULL);
-		ret = exec_simple_cmd(&dsps->os,
-				      OSSP_DSP_SET_TRIGGER, &i, NULL);
-		if (ret)
-			goto err;
-		IOCTL_RETURN(0, NULL);
-
-	case SNDCTL_DSP_GETOSPACE:
-	case SNDCTL_DSP_GETISPACE: {
-		struct audio_buf_info info;
-
-		ret = -EINVAL;
-		if (cmd == SNDCTL_DSP_GETOSPACE) {
-			if (!(dsps->rw & (1 << PLAY)))
-				goto err;
-			op = OSSP_DSP_GET_OSPACE;
-		} else {
-			if (!(dsps->rw & (1 << REC)))
-				goto err;
-			op = OSSP_DSP_GET_ISPACE;
-		}
-
-		PREP_UARG(NULL, &info);
-		ret = exec_simple_cmd(&dsps->os, op, NULL, &info);
-		if (ret)
-			goto err;
-		IOCTL_RETURN(0, &info);
-	}
-
-	case SNDCTL_DSP_GETOPTR:
-	case SNDCTL_DSP_GETIPTR: {
-		struct count_info info;
-
-		op = cmd == SNDCTL_DSP_GETOPTR ? OSSP_DSP_GET_OPTR
-					       : OSSP_DSP_GET_IPTR;
-		PREP_UARG(NULL, &info);
-		ret = exec_simple_cmd(&dsps->os, op, NULL, &info);
-		if (ret)
-			goto err;
-		IOCTL_RETURN(0, &info);
-	}
-
-	case SNDCTL_DSP_GETODELAY:
-		PREP_UARG(NULL, &i);
-		i = 0;
-		ret = exec_simple_cmd(&dsps->os, OSSP_DSP_GET_ODELAY, NULL, &i);
-		IOCTL_RETURN(ret, &i);	/* always copy out result, 0 on err */
-
-	case SOUND_PCM_WRITE_FILTER:
-	case SOUND_PCM_READ_FILTER:
-		ret = -EIO;
-		goto err;
-
-	case SNDCTL_DSP_MAPINBUF:
-	case SNDCTL_DSP_MAPOUTBUF:
-		ret = -EINVAL;
-		goto err;
-
-	case SNDCTL_DSP_SETSYNCRO:
-	case SNDCTL_DSP_SETDUPLEX:
-	case SNDCTL_DSP_PROFILE:
-		IOCTL_RETURN(0, NULL);
-
-	default:
-		warn_os(os, "unknown ioctl 0x%x", cmd);
-		ret = -EINVAL;
-		goto err;
-	}
-	assert(0);	/* control shouldn't reach here */
-err:
-	fuse_reply_err(req, -ret);
-}
-
-#ifdef OSSP_MMAP
-static int dsp_mmap_dir(int prot)
-{
-	if (!(prot & PROT_WRITE))
-		return REC;
-	return PLAY;
-}
-
-static void dsp_mmap(fuse_req_t req, void *addr, size_t len, int prot,
-		     int flags, off_t offset, struct fuse_file_info *fi,
-		     uint64_t mh)
-{
-	int dir = dsp_mmap_dir(prot);
-	struct ossp_dsp_mmap_arg arg = { };
-	struct ossp_stream *os;
-	struct ossp_dsp_stream *dsps;
-	ssize_t ret;
-
-	os = find_os(fi->fh);
-	if (!os) {
-		fuse_reply_err(req, EBADF);
-		return;
-	}
-	dsps = os_to_dsps(os);
-
-	if (!os->mmap_off || len > os->mmap_size / 2) {
-		fuse_reply_err(req, EINVAL);
-		return;
-	}
-
-	pthread_mutex_lock(&os->mmap_mutex);
-
-	ret = -EBUSY;
-	if (dsps->mmapped & (1 << dir))
-		goto out_unlock;
-
-	arg.dir = dir;
-	arg.size = len;
-
-	ret = exec_simple_cmd(os, OSSP_DSP_MMAP, &arg, NULL);
-	if (ret == 0)
-		dsps->mmapped |= 1 << dir;
-
-out_unlock:
-	pthread_mutex_unlock(&os->mmap_mutex);
-
-	if (ret == 0)
-		fuse_reply_mmap(req, os->mmap_off + dir * os->mmap_size / 2, 0);
-	else
-		fuse_reply_err(req, -ret);
-}
-
-static void dsp_munmap(fuse_req_t req, size_t len, struct fuse_file_info *fi,
-		       off_t offset, uint64_t mh)
-{
-	struct ossp_stream *os;
-	struct ossp_dsp_stream *dsps;
-	int dir, rc;
-
-	os = find_os(fi->fh);
-	if (!os)
-		goto out;
-	dsps = os_to_dsps(os);
-
-	pthread_mutex_lock(&os->mmap_mutex);
-
-	for (dir = 0; dir < 2; dir++)
-		if (offset == os->mmap_off + dir * os->mmap_size / 2)
-			break;
-	if (dir == 2 || len > os->mmap_size / 2) {
-		warn_os(os, "invalid munmap request "
-			"offset=%llu len=%zu mmapped=0x%x",
-			(unsigned long long)offset, len, dsps->mmapped);
-		goto out_unlock;
-	}
-
-	rc = exec_simple_cmd(os, OSSP_DSP_MUNMAP, &dir, NULL);
-	if (rc)
-		warn_ose(os, rc, "MUNMAP failed for dir=%d", dir);
-
-	dsps->mmapped &= ~(1 << dir);
-
-out_unlock:
-	pthread_mutex_unlock(&os->mmap_mutex);
-out:
-	fuse_reply_none(req);
-}
-#endif
-
-
-/***************************************************************************
- * Notify poller
- */
-
-static void *notify_poller(void *arg)
-{
-	struct epoll_event events[1024];
-	int i, nfds;
-
-repeat:
-	nfds = epoll_wait(notify_epfd, events, ARRAY_SIZE(events), -1);
-	for (i = 0; i < nfds; i++) {
-		int do_notify = 0;
-		struct ossp_stream *os;
-		struct ossp_notify notify;
-		ssize_t ret;
-
-		os = find_os_by_notify_rx(events[i].data.fd);
-		if (!os) {
-			err("can't find stream for notify_rx fd %d",
-			    events[i].data.fd);
-			epoll_ctl(notify_epfd, EPOLL_CTL_DEL, events[i].data.fd,
-				  NULL);
-			/* we don't know what's going on, don't close the fd */
-			continue;
-		}
-
-		while ((ret = read(os->notify_rx,
-				   &notify, sizeof(notify))) > 0) {
-			if (os->dead)
-				continue;
-			if (ret != sizeof(notify)) {
-				warn_os(os, "short read on notify_rx (%zu, "
-					"expected %zu), killing the stream",
-					ret, sizeof(notify));
-				os->dead = 1;
-				break;
-			}
-			if (notify.magic != OSSP_NOTIFY_MAGIC) {
-				warn_os(os, "invalid magic on notification, "
-					"killing the stream");
-				os->dead = 1;
-				break;
-			}
-
-			if (notify.opcode >= OSSP_NR_NOTIFY_OPCODES)
-				goto unknown;
-
-			dbg1_os(os, "NOTIFY %s", ossp_notify_str[notify.opcode]);
-
-			switch (notify.opcode) {
-			case OSSP_NOTIFY_POLL:
-				do_notify = 1;
-				break;
-			case OSSP_NOTIFY_OBITUARY:
-				os->dead = 1;
-				break;
-			case OSSP_NOTIFY_VOLCHG:
-				pthread_mutex_lock(&mixer_mutex);
-				os->mixer->modify_counter++;
-				pthread_mutex_unlock(&mixer_mutex);
-				break;
-			default:
-			unknown:
-				warn_os(os, "unknown notification %d",
-					notify.opcode);
-			}
-		}
-		if (ret == 0)
-			os->dead = 1;
-		else if (ret < 0 && errno != EAGAIN) {
-			warn_ose(os, -errno, "read fail on notify fd");
-			os->dead = 1;
-		}
-
-		if (!do_notify && !os->dead)
-			continue;
-
-		pthread_mutex_lock(&mutex);
-
-		if (os->ph) {
-			fuse_lowlevel_notify_poll(os->ph);
-			fuse_pollhandle_destroy(os->ph);
-			os->ph = NULL;
-		}
-
-		if (os->dead) {
-			dbg0_os(os, "removing %d from notify poll list",
-				os->notify_rx);
-			epoll_ctl(notify_epfd, EPOLL_CTL_DEL, os->notify_rx,
-				  NULL);
-			close(os->notify_rx);
-			os->notify_rx = -1;
-			pthread_cond_broadcast(&notify_poller_kill_wait);
-		}
-
-		pthread_mutex_unlock(&mutex);
-	}
-	goto repeat;
-}
-
-
-/***************************************************************************
- * Slave corpse reaper
- */
-
-static void *slave_reaper(void *arg)
-{
-	struct ossp_stream *os;
-	int status;
-	pid_t pid;
-
-	pthread_mutex_lock(&mutex);
-repeat:
-	while (list_empty(&slave_corpse_list))
-		pthread_cond_wait(&slave_reaper_wait, &mutex);
-
-	os = list_first_entry(&slave_corpse_list, struct ossp_stream, link);
-	list_del_init(&os->link);
-
-	pthread_mutex_unlock(&mutex);
-
-	do {
-		pid = waitpid(os->slave_pid, &status, 0);
-	} while (pid < 0 && errno == EINTR);
-
-	if (pid < 0) {
-		if (errno == ECHILD)
-			warn_ose(os, -errno, "slave %d already gone?",
-				 os->slave_pid);
-		else
-			fatal_e(-errno, "waitpid(%d) failed", os->slave_pid);
-	}
-
-	pthread_mutex_lock(&mutex);
-
-	dbg1_os(os, "slave %d reaped", os->slave_pid);
-	__clear_bit(os->id, os_id_bitmap);
-	free(os);
-
-	goto repeat;
-}
-
-
-/***************************************************************************
- * Stuff to bind and start everything
- */
-
-static void ossp_daemonize(void)
-{
-	int fd, pfd[2];
-	pid_t pid;
-	ssize_t ret;
-	int err;
-
-	fd = open("/dev/null", O_RDWR);
-	if (fd >= 0) {
-		dup2(fd, 0);
-		dup2(fd, 1);
-		dup2(fd, 2);
-		if (fd > 2)
-			close(fd);
-	}
-
-	if (pipe(pfd))
-		fatal_e(-errno, "failed to create pipe for init wait");
-
-	if (fcntl(pfd[0], F_SETFD, FD_CLOEXEC) < 0 ||
-	    fcntl(pfd[1], F_SETFD, FD_CLOEXEC) < 0)
-		fatal_e(-errno, "failed to set CLOEXEC on init wait pipe");
-
-	pid = fork();
-	if (pid < 0)
-		fatal_e(-errno, "failed to fork for daemon");
-
-	if (pid == 0) {
-		close(pfd[0]);
-		init_wait_fd = pfd[1];
-
-		/* be evil, my child */
-		chdir("/");
-		setsid();
-		return;
-	}
-
-	/* wait for init completion and pass over success indication */
-	close(pfd[1]);
-
-	do {
-		ret = read(pfd[0], &err, sizeof(err));
-	} while (ret < 0 && errno == EINTR);
-
-	if (ret == sizeof(err) && err == 0)
-		exit(0);
-
-	fatal("daemon init failed ret=%zd err=%d", ret, err);
-	exit(1);
-}
-
-static void ossp_init_done(void *userdata)
-{
-	/* init complete, notify parent if it's waiting */
-	if (init_wait_fd >= 0) {
-		ssize_t ret;
-		int err = 0;
-
-		ret = write(init_wait_fd, &err, sizeof(err));
-		if (ret != sizeof(err))
-			fatal_e(-errno, "failed to notify init completion, "
-				"ret=%zd", ret);
-		close(init_wait_fd);
-		init_wait_fd = -1;
-	}
-}
-
-static const struct cuse_lowlevel_ops mixer_ops = {
-	.open			= mixer_open,
-	.release		= mixer_release,
-	.ioctl			= mixer_ioctl,
-};
-
-static const struct cuse_lowlevel_ops dsp_ops = {
-	.init_done		= ossp_init_done,
-	.open			= dsp_open,
-	.release		= dsp_release,
-	.read			= dsp_read,
-	.write			= dsp_write,
-	.poll			= dsp_poll,
-	.ioctl			= dsp_ioctl,
-#ifdef OSSP_MMAP
-	.mmap			= dsp_mmap,
-	.munmap			= dsp_munmap,
-#endif
-};
-
-static const struct cuse_lowlevel_ops adsp_ops = {
-	.open			= adsp_open,
-	.release		= dsp_release,
-	.read			= dsp_read,
-	.write			= dsp_write,
-	.poll			= dsp_poll,
-	.ioctl			= dsp_ioctl,
-#ifdef OSSP_MMAP
-	.mmap			= dsp_mmap,
-	.munmap			= dsp_munmap,
-#endif
-};
-
-static const char *usage =
-"usage: osspd [options]\n"
-"\n"
-"options:\n"
-"    --help            print this help message\n"
-"    --dsp=NAME        DSP device name (default dsp)\n"
-"    --dsp-maj=MAJ     DSP device major number (default 14)\n"
-"    --dsp-min=MIN     DSP device minor number (default 3)\n"
-"    --adsp=NAME       Aux DSP device name (default adsp, blank to disable)\n"
-"    --adsp-maj=MAJ    Aux DSP device major number (default 14)\n"
-"    --adsp-min=MIN    Aux DSP device minor number (default 12)\n"
-"    --mixer=NAME      mixer device name (default mixer, blank to disable)\n"
-"    --mixer-maj=MAJ   mixer device major number (default 14)\n"
-"    --mixer-min=MIN   mixer device minor number (default 0)\n"
-"    --max=MAX         maximum number of open streams (default 256)\n"
-"    --umax=MAX        maximum number of open streams per UID (default --max)\n"
-"    --exit-on-idle    exit if idle\n"
-"    --dsp-slave=PATH  DSP slave (default ossp-padsp in the same dir)\n"
-"    --log=LEVEL       log level (0..6)\n"
-"    --timestamp       timestamp log messages\n"
-"    -v                increase verbosity, can be specified multiple times\n"
-"    -f                Run in foreground (don't daemonize)\n"
-"\n";
-
-struct ossp_param {
-	char			*dsp_name;
-	unsigned		dsp_major;
-	unsigned		dsp_minor;
-	char			*adsp_name;
-	unsigned		adsp_major;
-	unsigned		adsp_minor;
-	char			*mixer_name;
-	unsigned		mixer_major;
-	unsigned		mixer_minor;
-	unsigned		max_streams;
-	unsigned		umax_streams;
-	char			*dsp_slave_path;
-	unsigned		log_level;
-	int			exit_on_idle;
-	int			timestamp;
-	int			fg;
-	int			help;
-};
-
-#define OSSP_OPT(t, p) { t, offsetof(struct ossp_param, p), 1 }
-
-static const struct fuse_opt ossp_opts[] = {
-	OSSP_OPT("--dsp=%s",		dsp_name),
-	OSSP_OPT("--dsp-maj=%u",	dsp_major),
-	OSSP_OPT("--dsp-min=%u",	dsp_minor),
-	OSSP_OPT("--adsp=%s",		adsp_name),
-	OSSP_OPT("--adsp-maj=%u",	adsp_major),
-	OSSP_OPT("--adsp-min=%u",	adsp_minor),
-	OSSP_OPT("--mixer=%s",		mixer_name),
-	OSSP_OPT("--mixer-maj=%u",	mixer_major),
-	OSSP_OPT("--mixer-min=%u",	mixer_minor),
-	OSSP_OPT("--max=%u",		max_streams),
-	OSSP_OPT("--umax=%u",		umax_streams),
-	OSSP_OPT("--exit-on-idle",	exit_on_idle),
-	OSSP_OPT("--dsp-slave=%s",	dsp_slave_path),
-	OSSP_OPT("--timestamp",		timestamp),
-	OSSP_OPT("--log=%u",		log_level),
-	OSSP_OPT("-f",			fg),
-	FUSE_OPT_KEY("-h",		0),
-	FUSE_OPT_KEY("--help",		0),
-	FUSE_OPT_KEY("-v",		1),
-	FUSE_OPT_END
-};
-
-static struct fuse_session *setup_ossp_cuse(const struct cuse_lowlevel_ops *ops,
-					    const char *name, int major,
-					    int minor, int argc, char **argv)
-{
-	char name_buf[128];
-	const char *bufp = name_buf;
-	struct cuse_info ci = { .dev_major = major, .dev_minor = minor,
-				.dev_info_argc = 1, .dev_info_argv = &bufp,
-				.flags = CUSE_UNRESTRICTED_IOCTL };
-	struct fuse_session *se;
-	int fd;
-
-	snprintf(name_buf, sizeof(name_buf), "DEVNAME=%s", name);
-
-	se = cuse_lowlevel_setup(argc, argv, &ci, ops, NULL, NULL);
-	if (!se) {
-		err("failed to setup %s CUSE", name);
-		return NULL;
-	}
-
-	fd = fuse_chan_fd(fuse_session_next_chan(se, NULL));
-	if (
-#ifdef OSSP_MMAP
-		fd != fuse_mmap_fd(se) &&
-#endif
-		fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
-		err_e(-errno, "failed to set CLOEXEC on %s CUSE fd", name);
-		cuse_lowlevel_teardown(se);
-		return NULL;
-	}
-
-	return se;
-}
-
-static void *cuse_worker(void *arg)
-{
-	struct fuse_session *se = arg;
-	int rc;
-
-	rc = fuse_session_loop_mt(se);
-	cuse_lowlevel_teardown(se);
-
-	return (void *)(unsigned long)rc;
-}
-
-static int process_arg(void *data, const char *arg, int key,
-		       struct fuse_args *outargs)
-{
-	struct ossp_param *param = data;
-
-	switch (key) {
-	case 0:
-		fprintf(stderr, usage);
-		param->help = 1;
-		return 0;
-	case 1:
-		param->log_level++;
-		return 0;
-	}
-	return 1;
-}
-
-int main(int argc, char **argv)
-{
-	static struct ossp_param param = {
-		.dsp_name = DFL_DSP_NAME,
-		.dsp_major = DFL_DSP_MAJOR, .dsp_minor = DFL_DSP_MINOR,
-		.adsp_name = DFL_ADSP_NAME,
-		.adsp_major = DFL_ADSP_MAJOR, .adsp_minor = DFL_ADSP_MINOR,
-		.mixer_name = DFL_MIXER_NAME,
-		.mixer_major = DFL_MIXER_MAJOR, .mixer_minor = DFL_MIXER_MINOR,
-		.max_streams = DFL_MAX_STREAMS,
-	};
-	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
-	char path_buf[PATH_MAX], *dir;
-	char adsp_buf[64] = "", mixer_buf[64] = "";
-	struct sigaction sa;
-	struct stat stat_buf;
-	ssize_t ret;
-	unsigned u;
-
-	snprintf(ossp_log_name, sizeof(ossp_log_name), "osspd");
-	param.log_level = ossp_log_level;
-
-	if (fuse_opt_parse(&args, &param, ossp_opts, process_arg))
-		fatal("failed to parse arguments");
-
-	if (param.help)
-		return 0;
-
-	max_streams = param.max_streams;
-	hashtbl_size = max_streams / 2 + 13;
-
-	umax_streams = max_streams;
-	if (param.umax_streams)
-		umax_streams = param.umax_streams;
-	if (param.log_level > OSSP_LOG_MAX)
-		param.log_level = OSSP_LOG_MAX;
-	if (!param.fg)
-		param.log_level = -param.log_level;
-	ossp_log_level = param.log_level;
-	ossp_log_timestamp = param.timestamp;
-
-	if (!param.fg)
-		ossp_daemonize();
-
-	/* daemonization already handled, prevent forking inside FUSE */
-	fuse_opt_add_arg(&args, "-f");
-
-	info("OSS Proxy v%s (C) 2008-2010 by Tejun Heo <teheo@suse.de>",
-	     OSSP_VERSION);
-
-	/* ignore stupid SIGPIPEs */
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_IGN;
-	if (sigaction(SIGPIPE, &sa, NULL))
-		fatal_e(-errno, "failed to ignore SIGPIPE");
-
-	/* determine slave path and check for availability */
-	ret = readlink("/proc/self/exe", path_buf, PATH_MAX - 1);
-	if (ret < 0)
-		fatal_e(-errno, "failed to determine executable path");
-	path_buf[ret] = '\0';
-	dir = dirname(path_buf);
-
-	if (param.dsp_slave_path) {
-		strncpy(dsp_slave_path, param.dsp_slave_path, PATH_MAX - 1);
-		dsp_slave_path[PATH_MAX - 1] = '\0';
-	} else {
-		ret = snprintf(dsp_slave_path, PATH_MAX, "%s/%s",
-			       dir, "ossp-padsp");
-		if (ret >= PATH_MAX)
-			fatal("dsp slave pathname too long");
-	}
-
-	if (stat(dsp_slave_path, &stat_buf))
-		fatal_e(-errno, "failed to stat %s", dsp_slave_path);
-	if (!S_ISREG(stat_buf.st_mode) || !(stat_buf.st_mode & 0444))
-		fatal("%s is not executable", dsp_slave_path);
-
-	/* allocate tables */
-	os_id_bitmap = calloc(BITS_TO_LONGS(max_streams), sizeof(long));
-	mixer_tbl = calloc(hashtbl_size, sizeof(mixer_tbl[0]));
-	os_tbl = calloc(hashtbl_size, sizeof(os_tbl[0]));
-	os_pgrp_tbl = calloc(hashtbl_size, sizeof(os_pgrp_tbl[0]));
-	os_notify_tbl = calloc(hashtbl_size, sizeof(os_notify_tbl[0]));
-	if (!os_id_bitmap || !mixer_tbl || !os_tbl || !os_pgrp_tbl ||
-	    !os_notify_tbl)
-		fatal("failed to allocate stream hash tables");
-	for (u = 0; u < hashtbl_size; u++) {
-		INIT_LIST_HEAD(&mixer_tbl[u]);
-		INIT_LIST_HEAD(&os_tbl[u]);
-		INIT_LIST_HEAD(&os_pgrp_tbl[u]);
-		INIT_LIST_HEAD(&os_notify_tbl[u]);
-	}
-	__set_bit(0, os_id_bitmap);	/* don't use id 0 */
-
-	/* create mixer delayed reference worker */
-	ret = -pthread_create(&mixer_delayed_put_thread, NULL,
-			      mixer_delayed_put_worker, NULL);
-	if (ret)
-		fatal_e(ret, "failed to create mixer delayed put worker");
-
-	/* if exit_on_idle, touch mixer for pgrp0 */
-	exit_on_idle = param.exit_on_idle;
-	if (exit_on_idle) {
-		struct ossp_mixer *mixer;
-
-		mixer = get_mixer(0);
-		if (!mixer)
-			fatal("failed to touch idle mixer");
-		put_mixer(mixer);
-	}
-
-	/* create notify epoll and kick off watcher thread */
-	notify_epfd = epoll_create(max_streams);
-	if (notify_epfd < 0)
-		fatal_e(-errno, "failed to create notify epoll");
-	if (fcntl(notify_epfd, F_SETFD, FD_CLOEXEC) < 0)
-		fatal_e(-errno, "failed to set CLOEXEC on notify epfd");
-
-	ret = -pthread_create(&notify_poller_thread, NULL, notify_poller, NULL);
-	if (ret)
-		fatal_e(ret, "failed to create notify poller thread");
-
-	/* create reaper for slave corpses */
-	ret = -pthread_create(&slave_reaper_thread, NULL, slave_reaper, NULL);
-	if (ret)
-		fatal_e(ret, "failed to create slave reaper thread");
-
-	/* we're set, let's setup fuse structures */
-	if (strlen(param.mixer_name))
-		mixer_se = setup_ossp_cuse(&mixer_ops, param.mixer_name,
-					   param.mixer_major, param.mixer_minor,
-					   args.argc, args.argv);
-	if (strlen(param.adsp_name))
-		adsp_se = setup_ossp_cuse(&dsp_ops, param.adsp_name,
-					  param.adsp_major, param.adsp_minor,
-					  args.argc, args.argv);
-
-	dsp_se = setup_ossp_cuse(&dsp_ops, param.dsp_name,
-				 param.dsp_major, param.dsp_minor,
-				 args.argc, args.argv);
-	if (!dsp_se)
-		fatal("can't create dsp, giving up");
-
-	if (mixer_se)
-		snprintf(mixer_buf, sizeof(mixer_buf), ", %s (%d:%d)",
-			 param.mixer_name, param.mixer_major, param.mixer_minor);
-	if (adsp_se)
-		snprintf(adsp_buf, sizeof(adsp_buf), ", %s (%d:%d)",
-			 param.adsp_name, param.adsp_major, param.adsp_minor);
-
-	info("Creating %s (%d:%d)%s%s", param.dsp_name, param.dsp_major,
-	     param.dsp_minor, adsp_buf, mixer_buf);
-
-	/* start threads for mixer and adsp */
-	if (mixer_se) {
-		ret = -pthread_create(&cuse_mixer_thread, NULL,
-				      cuse_worker, mixer_se);
-		if (ret)
-			err_e(ret, "failed to create mixer worker");
-	}
-	if (adsp_se) {
-		ret = -pthread_create(&cuse_adsp_thread, NULL,
-				      cuse_worker, adsp_se);
-		if (ret)
-			err_e(ret, "failed to create adsp worker");
-	}
-
-	/* run CUSE for /dev/dsp in the main thread */
-	ret = (ssize_t)cuse_worker(dsp_se);
-	if (ret < 0)
-		fatal("dsp worker failed");
-	return 0;
-}
diff --git a/osstest.c b/osstest.c
deleted file mode 100644
index 53c3edc..0000000
--- a/osstest.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/* Simple oss testsuite
- *
- * Copyright (C) 2009 Maarten Lankhorst <m.b.lankhorst@gmail.com>
- *
- * This file is released under the GPLv2.
- */
-
-#include <sys/types.h>
-#include <sys/soundcard.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <poll.h>
-#include <sys/mman.h>
-#include <stdlib.h>
-
-#define MIXERDEV "/dev/mixer"
-#define DSPDEV "/dev/dsp"
-
-/* Test macros */
-
-static int errors, success;
-static int report_success = 1;
-
-#define ok(a, b, c...) do { \
-	if (!(a)) { \
-		fprintf(stderr, "%s@%d test failed (%s): " b "\n", __func__, __LINE__, #a, ##c); \
-		++errors; \
-	} else { \
-		if (report_success) \
-			printf("%s@%d test succeeded (%s)\n", __func__, __LINE__, #a); \
-		++success; \
-	} } while (0)
-
-static int mixerfd, dspfd;
-
-static int reopen(int blocking)
-{
-	close(dspfd);
-	if (!blocking)
-		blocking = O_NDELAY;
-	else
-		blocking = 0;
-	dspfd = open(DSPDEV, O_RDWR|blocking);
-	return dspfd;
-}
-
-static void test_ro(int fd)
-{
-	int ret;
-	char buf[1024];
-	struct audio_buf_info abi;
-	memset(buf, 0, sizeof(buf));
-
-	ret = read(fd, buf, sizeof(buf));
-	ok(ret >= 0, "%s", strerror(errno));
-
-	ret = write(fd, buf, sizeof(buf));
-	ok(ret < 0, "read %d bytes", ret);
-
-	ret = ioctl(fd, SNDCTL_DSP_GETISPACE, &abi);
-	ok(ret >= 0, "%s", strerror(errno));
-
-	ret = ioctl(fd, SNDCTL_DSP_GETOSPACE, &abi);
-	ok(ret < 0, "%s", strerror(errno));
-	if (ret < 0)
-		ok(errno == EINVAL, "Invalid errno: %s", strerror(errno));
-}
-
-static void test_wo(int fd)
-{
-	int ret;
-	char buf[1024];
-	struct audio_buf_info abi;
-	memset(buf, 0, sizeof(buf));
-
-	ret = read(fd, buf, sizeof(buf));
-	ok(ret < 0, "read %d bytes", ret);
-
-	ret = write(fd, buf, sizeof(buf));
-	ok(ret >= 0, "%s", strerror(errno));
-
-	ret = ioctl(fd, SNDCTL_DSP_GETISPACE, &abi);
-	ok(ret < 0, "%s", strerror(errno));
-	if (ret < 0)
-		ok(errno == EINVAL, "Invalid errno: %s", strerror(errno));
-
-	ret = ioctl(fd, SNDCTL_DSP_GETOSPACE, &abi);
-	ok(ret >= 0, "%s", strerror(errno));
-}
-
-static void test_rw(int fd)
-{
-	int ret;
-	char buf[1024];
-	struct audio_buf_info abi;
-	memset(buf, 0, sizeof(buf));
-
-	ret = read(fd, buf, sizeof(buf));
-	ok(ret >= 0, "%s", strerror(errno));
-
-	ret = write(fd, buf, sizeof(buf));
-	ok(ret >= 0, "%s", strerror(errno));
-
-	ret = ioctl(fd, SNDCTL_DSP_GETISPACE, &abi);
-	ok(ret >= 0, "%s", strerror(errno));
-
-	ret = ioctl(fd, SNDCTL_DSP_GETOSPACE, &abi);
-	ok(ret >= 0, "%s", strerror(errno));
-}
-
-static void test_open(void)
-{
-	int ro_fd, rw_fd, wo_fd;
-
-	mixerfd = open(MIXERDEV, O_RDONLY|O_NDELAY);
-	ok(mixerfd >= 0, "%s", strerror(errno));
-
-
-	/* In order to make this work it has to be serialized
-	 * alsa's kernel emulation can only have device open once
-	 * so do some specific smokescreen tests here
-	 * and then open dsp for testing
-	 */
-	ro_fd = open(DSPDEV, O_RDONLY);
-	ok(ro_fd >= 0, "%s", strerror(errno));
-
-	if (ro_fd >= 0)
-		test_ro(ro_fd);
-
-	close(ro_fd);
-
-	wo_fd = open(DSPDEV, O_WRONLY);
-	ok(wo_fd >= 0, "%s", strerror(errno));
-
-	if (wo_fd >= 0)
-		test_wo(wo_fd);
-
-	close(wo_fd);
-
-	rw_fd = open(DSPDEV, O_RDWR);
-	ok(rw_fd >= 0, "%s", strerror(errno));
-
-	if (rw_fd >= 0)
-		test_rw(rw_fd);
-
-	dspfd = rw_fd;
-}
-
-static void test_mixer(void)
-{
-	int ret;
-	struct mixer_info info;
-	memset(&info, 0, sizeof(info));
-
-	ret = ioctl(mixerfd, SOUND_MIXER_INFO, &info);
-	ok(ret >= 0, "%s", strerror(errno));
-	if (ret >= 0) {
-		printf("Mixer id: %s\n", info.id);
-		printf("Name: %s\n", info.name);
-	}
-}
-
-static void test_trigger(int fd)
-{
-	int ret, i;
-
-	ret = ioctl(fd, SNDCTL_DSP_GETTRIGGER, &i);
-	ok(ret == 0, "Returned error %s", strerror(errno));
-	ok(i == (PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT), "i is set to %d", i);
-
-	i = 0;
-	ret = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &i);
-	ok(ret == 0, "Returned error %s", strerror(errno));
-	ok(i == 0,  "Wrong i returned");
-
-	i = PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT;
-	ret = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &i);
-	ok(ret == 0, "Returned error %s", strerror(errno));
-	ok(i == (PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT), "i has value %d", i);
-
-	ret = ioctl(fd, SNDCTL_DSP_POST, NULL);
-	ok(ret == 0, "Returned error %s", strerror(errno));
-}
-
-static void test_mmap(int fd)
-{
-	char *area;
-	int ret;
-	char buf[24];
-
-	area = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-	ok(area != MAP_FAILED, "Failed to map: %s\n", strerror(errno));
-
-	if (area == MAP_FAILED)
-		return;
-
-	ret = write(fd, &buf, sizeof(buf));
-	ok(ret == -1, "write after mmap returned %i\n", ret);
-	if (ret == -1)
-		ok(errno == ENXIO, "Error returned is %s\n", strerror(errno));
-
-	munmap(area, 8192);
-}
-
-static void test_notify(int fd)
-{
-	struct audio_buf_info bi;
-	char *bytes = NULL;
-	int ret, written;
-	struct pollfd pfd = { fd, POLLOUT };
-	int rounds = 20;
-
-	ioctl(fd, SNDCTL_DSP_GETOSPACE, &bi);
-
-	bytes = calloc(1, bi.fragsize);
-	written = 0;
-	ok(0, "Fragsize: %i, bytes: %i\n", bi.fragsize, bi.bytes);
-	while (written + bi.fragsize - 1 < bi.bytes)
-	{
-		ret = write(fd, bytes, bi.fragsize);
-		ok(ret == bi.fragsize, "Returned: %i instead of %i\n",
-		   ret, bi.fragsize);
-		if (ret > 0)
-			written += ret;
-	};
-
-	while (rounds--)
-	{
-		ret = poll(&pfd, 1, -1);
-		ok(ret > 0, "Poll returned %i\n", ret);
-		if (ret < 0)
-			break;
-		ret = write(fd, bytes, bi.fragsize);
-		if (ret < 0) ret = -errno;
-		ok(ret == bi.fragsize, "Returned: %i instead of %i\n",
-		   ret, bi.fragsize);
-	}
-}
-
-int main()
-{
-	test_open();
-	if (mixerfd >= 0)
-		test_mixer();
-
-	if (reopen(1) >= 0)
-		test_trigger(dspfd);
-
-	if (reopen(0) >= 0)
-		test_notify(dspfd);
-
-	if (reopen(1) >= 0)
-		test_mmap(dspfd);
-
-	close(mixerfd);
-	close(dspfd);
-	printf("Tests: %d errors %d success\n", errors, success);
-	return errors > 127 ? 127 : errors;
-}
-
-- 
2.39.5