aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile2
-rw-r--r--lib/atf/Makefile.inc2
-rw-r--r--lib/atf/libatf-c++/Makefile1
-rw-r--r--lib/atf/libatf-c++/tests/Makefile2
-rw-r--r--lib/atf/libatf-c/Makefile1
-rw-r--r--lib/atf/libatf-c/tests/Makefile2
-rw-r--r--lib/clang/freebsd_cc_version.h2
-rw-r--r--lib/clang/include/lld/Common/Version.inc2
-rw-r--r--lib/libbe/Makefile1
-rw-r--r--lib/libbsdstat/bsdstat.h2
-rw-r--r--lib/libbsm/Makefile9
-rw-r--r--lib/libbz2/Makefile4
-rw-r--r--lib/libc/aarch64/string/timingsafe_memcmp.S2
-rw-r--r--lib/libc/gdtoa/_hdtoa.c3
-rw-r--r--lib/libc/gdtoa/_hldtoa.c3
-rw-r--r--lib/libc/gen/Symbol.map2
-rw-r--r--lib/libc/gen/fts-compat.c2
-rw-r--r--lib/libc/gen/fts-compat11.c2
-rw-r--r--lib/libc/gen/gen-compat.h48
-rw-r--r--lib/libc/gen/getgrouplist.329
-rw-r--r--lib/libc/gen/getgrouplist.c6
-rw-r--r--lib/libc/gen/initgroups.3101
-rw-r--r--lib/libc/gen/initgroups.c55
-rw-r--r--lib/libc/gen/psignal.39
-rw-r--r--lib/libc/gen/sysconf.c2
-rw-r--r--lib/libc/include/compat.h1
-rw-r--r--lib/libc/rpc/rpc_generic.c4
-rw-r--r--lib/libc/stdtime/Makefile.inc3
-rw-r--r--lib/libc/stdtime/ctime.339
-rw-r--r--lib/libc/stdtime/tzset.357
-rw-r--r--lib/libc/tests/stdio/printfloat_test.c13
-rw-r--r--lib/libc/tests/stdtime/Makefile1
-rw-r--r--lib/libc/tests/stdtime/detect_tz_changes_test.c113
-rw-r--r--lib/libc/tests/string/memcmp_test.c12
-rw-r--r--lib/libc/tests/tls/dso/Makefile1
-rw-r--r--lib/libc/tests/tls_dso/Makefile1
-rw-r--r--lib/libedit/Makefile3
-rw-r--r--lib/libedit/Makefile.inc1
-rw-r--r--lib/libexpat/expat_config.h18
-rw-r--r--lib/libexpat/libbsdxml.34
-rw-r--r--lib/libjail/jail.c26
-rw-r--r--lib/libkvm/kvm_proc.c9
-rw-r--r--lib/liblzma/Makefile4
-rw-r--r--lib/libmixer/Makefile2
-rw-r--r--lib/libpfctl/libpfctl.c8
-rw-r--r--lib/libpfctl/libpfctl.h4
-rw-r--r--lib/libpmc/Makefile4
-rw-r--r--lib/libprocstat/libprocstat.c10
-rw-r--r--lib/libsamplerate/Makefile4
-rw-r--r--lib/libsdp/Makefile3
-rw-r--r--lib/libsdp/sdp.34
-rw-r--r--lib/libsdp/sdp.h2
-rw-r--r--lib/libsdp/service.c2
-rw-r--r--lib/libstdbuf/Makefile1
-rw-r--r--lib/libstdthreads/Makefile2
-rw-r--r--lib/libsys/Symbol.map6
-rw-r--r--lib/libsys/getgroups.294
-rw-r--r--lib/libsys/jail.296
-rw-r--r--lib/libsys/kqueue.254
-rw-r--r--lib/libsys/setcred.27
-rw-r--r--lib/libsys/setgroups.299
-rw-r--r--lib/libufs/Makefile4
-rw-r--r--lib/libunbound/Makefile31
-rw-r--r--lib/libunbound/config.h521
-rw-r--r--lib/libutil/login.conf.54
-rw-r--r--lib/libxo/tests/encoder/Makefile1
-rw-r--r--lib/liby/Makefile2
-rw-r--r--lib/msun/src/s_cpow.c5
-rw-r--r--lib/msun/src/s_cpowf.c5
-rw-r--r--lib/msun/src/s_cpowl.c5
-rw-r--r--lib/ncurses/Makefile.inc1
-rw-r--r--lib/ncurses/form/Makefile1
-rw-r--r--lib/ncurses/ncurses/Makefile1
-rw-r--r--lib/ncurses/panel/Makefile1
-rw-r--r--lib/ncurses/tinfo/Makefile1
-rw-r--r--lib/nss_tacplus/Makefile2
-rw-r--r--lib/virtual_oss/Makefile9
-rw-r--r--lib/virtual_oss/Makefile.inc3
-rw-r--r--lib/virtual_oss/bt/Makefile19
-rw-r--r--lib/virtual_oss/bt/avdtp.c720
-rw-r--r--lib/virtual_oss/bt/avdtp_signal.h139
-rw-r--r--lib/virtual_oss/bt/bt.c1061
-rw-r--r--lib/virtual_oss/bt/bt.h116
-rw-r--r--lib/virtual_oss/bt/cosdata-gen/Makefile12
-rw-r--r--lib/virtual_oss/bt/cosdata-gen/cosdata.c177
-rw-r--r--lib/virtual_oss/bt/sbc_coeffs.h69
-rw-r--r--lib/virtual_oss/bt/sbc_encode.c701
-rw-r--r--lib/virtual_oss/bt/sbc_encode.h82
-rw-r--r--lib/virtual_oss/null/Makefile10
-rw-r--r--lib/virtual_oss/null/null.c102
-rw-r--r--lib/virtual_oss/oss/Makefile10
-rw-r--r--lib/virtual_oss/oss/oss.c197
-rw-r--r--lib/virtual_oss/sndio/Makefile12
-rw-r--r--lib/virtual_oss/sndio/sndio.c203
94 files changed, 4645 insertions, 588 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 2b7cf2fdcb7d..d43e4d395f56 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -157,6 +157,7 @@ SUBDIR_DEPEND_liblzma= libthr
SUBDIR_DEPEND_libpcap= ofed
.endif
SUBDIR_DEPEND_nss_tacplus= libtacplus
+SUBDIR_DEPEND_virtual_oss= libsamplerate
# NB: keep these sorted by MK_* knobs
@@ -173,6 +174,7 @@ SUBDIR+= clang
.endif
SUBDIR.${MK_CUSE}+= libcuse
+SUBDIR.${MK_CUSE}+= virtual_oss
SUBDIR.${MK_TOOLCHAIN}+=libpe
SUBDIR.${MK_DIALOG}+= libdpv libfigpar
SUBDIR.${MK_FDT}+= libfdt
diff --git a/lib/atf/Makefile.inc b/lib/atf/Makefile.inc
index f8f329842eb4..bebed0280596 100644
--- a/lib/atf/Makefile.inc
+++ b/lib/atf/Makefile.inc
@@ -24,6 +24,8 @@
# SUCH DAMAGE.
#
+PACKAGE= atf
+LIB_PACKAGE=
CFLAGS+= -DHAVE_CONFIG_H
WARNS?= 3
diff --git a/lib/atf/libatf-c++/Makefile b/lib/atf/libatf-c++/Makefile
index 985a79b7dc03..4f4f7f12ec05 100644
--- a/lib/atf/libatf-c++/Makefile
+++ b/lib/atf/libatf-c++/Makefile
@@ -27,7 +27,6 @@
.include <src.opts.mk>
.include <bsd.init.mk>
-PACKAGE= tests
LIB_CXX= atf-c++
PRIVATELIB= true
SHLIB_MAJOR= 2
diff --git a/lib/atf/libatf-c++/tests/Makefile b/lib/atf/libatf-c++/tests/Makefile
index dc052c19df67..839c6902d6b1 100644
--- a/lib/atf/libatf-c++/tests/Makefile
+++ b/lib/atf/libatf-c++/tests/Makefile
@@ -1,7 +1,5 @@
.include <bsd.init.mk>
-PACKAGE= tests
-
TESTS_SUBDIRS= detail
ATF= ${SRCTOP}/contrib/atf
diff --git a/lib/atf/libatf-c/Makefile b/lib/atf/libatf-c/Makefile
index 4cfee2ed824f..c0890abc7640 100644
--- a/lib/atf/libatf-c/Makefile
+++ b/lib/atf/libatf-c/Makefile
@@ -27,7 +27,6 @@
.include <src.opts.mk>
.include <bsd.init.mk>
-PACKAGE= tests
LIB= atf-c
PRIVATELIB= true
SHLIB_MAJOR= 1
diff --git a/lib/atf/libatf-c/tests/Makefile b/lib/atf/libatf-c/tests/Makefile
index c81c18a91f00..5647e7b9fcbe 100644
--- a/lib/atf/libatf-c/tests/Makefile
+++ b/lib/atf/libatf-c/tests/Makefile
@@ -1,7 +1,5 @@
.include <bsd.init.mk>
-PACKAGE= tests
-
TESTS_SUBDIRS= detail
ATF= ${SRCTOP}/contrib/atf
diff --git a/lib/clang/freebsd_cc_version.h b/lib/clang/freebsd_cc_version.h
index 277744ae8624..b493dc96db5e 100644
--- a/lib/clang/freebsd_cc_version.h
+++ b/lib/clang/freebsd_cc_version.h
@@ -1 +1 @@
-#define FREEBSD_CC_VERSION 1500000
+#define FREEBSD_CC_VERSION 1600000
diff --git a/lib/clang/include/lld/Common/Version.inc b/lib/clang/include/lld/Common/Version.inc
index 0643da4abbf4..0def3da7469c 100644
--- a/lib/clang/include/lld/Common/Version.inc
+++ b/lib/clang/include/lld/Common/Version.inc
@@ -1,4 +1,4 @@
// Local identifier in __FreeBSD_version style
-#define LLD_FREEBSD_VERSION 1500001
+#define LLD_FREEBSD_VERSION 1600000
#define LLD_VERSION_STRING "19.1.7 (FreeBSD llvmorg-19.1.7-0-gcd708029e0b2-" __XSTRING(LLD_FREEBSD_VERSION) ")"
diff --git a/lib/libbe/Makefile b/lib/libbe/Makefile
index b04becc38d74..3ba456aee4b7 100644
--- a/lib/libbe/Makefile
+++ b/lib/libbe/Makefile
@@ -3,6 +3,7 @@ SHLIBDIR?= /lib
.include <src.opts.mk>
PACKAGE= zfs
+LIB_PACKAGE=
LIB= be
SHLIB_MAJOR= 1
SHLIB_MINOR= 0
diff --git a/lib/libbsdstat/bsdstat.h b/lib/libbsdstat/bsdstat.h
index 1b0d1f24e93f..b293cd652a72 100644
--- a/lib/libbsdstat/bsdstat.h
+++ b/lib/libbsdstat/bsdstat.h
@@ -76,7 +76,7 @@ struct fmt {
* classes derived from it are useful.
*/
struct bsdstat {
- const char *name; /* statistics name, e.g. wlanstats */
+ const char *name; /* statistics name, e.g. wlanstat */
const struct fmt *stats; /* statistics in class */
int nstats; /* number of stats */
#define FMTS_IS_STAT 0x80 /* the following two bytes are the stat id */
diff --git a/lib/libbsm/Makefile b/lib/libbsm/Makefile
index 67802eef62ac..4413a5dd79f7 100644
--- a/lib/libbsm/Makefile
+++ b/lib/libbsm/Makefile
@@ -1,9 +1,8 @@
-#
-#
+PACKAGE= audit
+LIB_PACKAGE=
-PACKAGE= lib${LIB}
-OPENBSMDIR= ${SRCTOP}/contrib/openbsm
-_LIBBSMDIR= ${OPENBSMDIR}/libbsm
+OPENBSMDIR= ${SRCTOP}/contrib/openbsm
+_LIBBSMDIR= ${OPENBSMDIR}/libbsm
LIB= bsm
SHLIB_MAJOR= 3
diff --git a/lib/libbz2/Makefile b/lib/libbz2/Makefile
index f7ea21b1a085..d773f202dd67 100644
--- a/lib/libbz2/Makefile
+++ b/lib/libbz2/Makefile
@@ -1,4 +1,6 @@
-PACKAGE= lib${LIB}
+PACKAGE= bzip2
+LIB_PACKAGE=
+
BZ2DIR= ${SRCTOP}/contrib/bzip2
.PATH: ${BZ2DIR}
diff --git a/lib/libc/aarch64/string/timingsafe_memcmp.S b/lib/libc/aarch64/string/timingsafe_memcmp.S
index 28fdd911a387..4cc10a152aa8 100644
--- a/lib/libc/aarch64/string/timingsafe_memcmp.S
+++ b/lib/libc/aarch64/string/timingsafe_memcmp.S
@@ -114,4 +114,4 @@ ENTRY(timingsafe_memcmp)
csetm w0, lo
csinc w0, w0, wzr, ls
ret
-END(timingsafe_bcmp)
+END(timingsafe_memcmp)
diff --git a/lib/libc/gdtoa/_hdtoa.c b/lib/libc/gdtoa/_hdtoa.c
index 8ae739acf0db..9c42630cd918 100644
--- a/lib/libc/gdtoa/_hdtoa.c
+++ b/lib/libc/gdtoa/_hdtoa.c
@@ -40,6 +40,7 @@
#define DBL_ADJ (DBL_MAX_EXP - 2)
#define SIGFIGS ((DBL_MANT_DIG + 3) / 4 + 1)
+#define MAX_HEX_DIGITS ((DBL_MANT_DIG + 3 - 1) / 4 + 1)
static const float one[] = { 1.0f, -1.0f };
@@ -111,7 +112,7 @@ __hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign,
s0 = rv_alloc(bufsize);
/* Round to the desired number of digits. */
- if (SIGFIGS > ndigits && ndigits > 0) {
+ if (MAX_HEX_DIGITS > ndigits && ndigits > 0) {
float redux = one[u.bits.sign];
int offset = 4 * ndigits + DBL_MAX_EXP - 4 - DBL_MANT_DIG;
u.bits.exp = offset;
diff --git a/lib/libc/gdtoa/_hldtoa.c b/lib/libc/gdtoa/_hldtoa.c
index 965d2349d103..5f10d12c5c09 100644
--- a/lib/libc/gdtoa/_hldtoa.c
+++ b/lib/libc/gdtoa/_hldtoa.c
@@ -65,6 +65,7 @@ typedef uint32_t manl_t;
#define LDBL_ADJ (LDBL_MAX_EXP - 2)
#define SIGFIGS ((LDBL_MANT_DIG + 3) / 4 + 1)
+#define MAX_HEX_DIGITS ((LDBL_MANT_DIG + 3 - 1) / 4 + 1)
static const float one[] = { 1.0f, -1.0f };
@@ -125,7 +126,7 @@ __hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
s0 = rv_alloc(bufsize);
/* Round to the desired number of digits. */
- if (SIGFIGS > ndigits && ndigits > 0) {
+ if (MAX_HEX_DIGITS > ndigits && ndigits > 0) {
float redux = one[u.bits.sign];
int offset = 4 * ndigits + LDBL_MAX_EXP - 4 - LDBL_MANT_DIG;
#ifdef __i386__
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 26f638568efc..494b65bc5cc1 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -193,7 +193,6 @@ FBSD_1.0 {
__isinff;
__isinfl;
isatty;
- initgroups;
jrand48;
lcong48;
ldexp;
@@ -462,6 +461,7 @@ FBSD_1.8 {
fdscandir_b;
fts_open_b;
glob_b;
+ initgroups;
inotify_add_watch;
inotify_init;
inotify_init1;
diff --git a/lib/libc/gen/fts-compat.c b/lib/libc/gen/fts-compat.c
index f87cabf085f7..62a1e0a81f62 100644
--- a/lib/libc/gen/fts-compat.c
+++ b/lib/libc/gen/fts-compat.c
@@ -44,9 +44,9 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include "gen-compat.h"
#include "fts-compat.h"
#include "un-namespace.h"
+#include "gen-compat.h"
#include "gen-private.h"
diff --git a/lib/libc/gen/fts-compat11.c b/lib/libc/gen/fts-compat11.c
index 0351ce5ac690..5abb378f5f08 100644
--- a/lib/libc/gen/fts-compat11.c
+++ b/lib/libc/gen/fts-compat11.c
@@ -43,9 +43,9 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include "gen-compat.h"
#include "fts-compat11.h"
#include "un-namespace.h"
+#include "gen-compat.h"
#include "gen-private.h"
diff --git a/lib/libc/gen/gen-compat.h b/lib/libc/gen/gen-compat.h
index 08e80ede6b6e..19b9addb4321 100644
--- a/lib/libc/gen/gen-compat.h
+++ b/lib/libc/gen/gen-compat.h
@@ -40,16 +40,50 @@ struct freebsd11_statfs;
struct freebsd11_dirent *freebsd11_readdir(DIR *);
int freebsd11_readdir_r(DIR *, struct freebsd11_dirent *,
struct freebsd11_dirent **);
-int freebsd11_stat(const char *, struct freebsd11_stat *);
-int freebsd11_lstat(const char *, struct freebsd11_stat *);
-int freebsd11_fstat(int, struct freebsd11_stat *);
-int freebsd11_fstatat(int, const char *, struct freebsd11_stat *, int);
-int freebsd11_statfs(const char *, struct freebsd11_statfs *);
-int freebsd11_getfsstat(struct freebsd11_statfs *, long, int);
int freebsd11_getmntinfo(struct freebsd11_statfs **, int);
char *freebsd11_devname(__uint32_t dev, __mode_t type);
-char *freebsd11_devname_r(__uint32_t dev, __mode_t type, char *buf, int len);
+char *freebsd11_devname_r(__uint32_t dev, __mode_t type, char *buf,
+ int len);
+
+/*
+ * We want freebsd11_fstat in C source to result in resolution to
+ * - fstat@FBSD_1.0 for libc.so (but we do not need the _definition_
+ * of this fstat, it is provided by libsys.so which we want to use).
+ * - freebsd11_fstat for libc.a (since if we make it fstat@FBSD_1.0
+ * for libc.a, then final linkage into static object ignores version
+ * and would reference fstat, which is the current syscall, not the
+ * compat syscall). libc.a provides the freebsd11_fstat implementation.
+ * Note that freebsd11_fstat from libc.a is not used for anything, but
+ * we make it correct nonetheless, just in case it would.
+ * This is arranged by COMPAT_SYSCALL, and libc can just use freebsd11_fstat.
+ */
+#ifdef PIC
+#define COMPAT_SYSCALL(rtype, fun, args, sym, ver) \
+ rtype fun args; __sym_compat(sym, fun, ver);
+#else
+#define COMPAT_SYSCALL(rtype, fun, args, sym, ver) \
+ rtype fun args;
+#endif
+
+COMPAT_SYSCALL(int, freebsd11_stat, (const char *, struct freebsd11_stat *),
+ stat, FBSD_1.0);
+COMPAT_SYSCALL(int, freebsd11_lstat, (const char *, struct freebsd11_stat *),
+ lstat, FBSD_1.0);
+COMPAT_SYSCALL(int, freebsd11_fstat, (int, struct freebsd11_stat *),
+ fstat, FBSD_1.0);
+COMPAT_SYSCALL(int, freebsd11_fstatat, (int, const char *,
+ struct freebsd11_stat *, int), fstatat, FBSD_1.1);
+
+COMPAT_SYSCALL(int, freebsd11_statfs, (const char *,
+ struct freebsd11_statfs *), statfs, FBSD_1.0);
+COMPAT_SYSCALL(int, freebsd11_getfsstat, (struct freebsd11_statfs *, long,
+ int), getfsstat, FBSD_1.0);
+
+COMPAT_SYSCALL(int, freebsd14_setgroups, (int gidsize, const __gid_t *gidset),
+ setgroups, FBSD_1.0);
+
+#undef COMPAT_SYSCALL
#endif /* _GEN_COMPAT_H_ */
diff --git a/lib/libc/gen/getgrouplist.3 b/lib/libc/gen/getgrouplist.3
index e9a980f99751..e3939fc2481a 100644
--- a/lib/libc/gen/getgrouplist.3
+++ b/lib/libc/gen/getgrouplist.3
@@ -1,5 +1,13 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 2025 The FreeBSD Foundation
+.\"
+.\" Portions of this documentation were written by Olivier Certner
+.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD
+.\" Foundation.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -25,12 +33,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd October 26, 2014
+.Dd August 29, 2025
.Dt GETGROUPLIST 3
.Os
.Sh NAME
.Nm getgrouplist
-.Nd calculate group access list
+.Nd produce a user's effective group list
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -40,16 +48,16 @@
.Sh DESCRIPTION
The
.Fn getgrouplist
-function reads through the group file and calculates
-the group access list for the user specified in
-.Fa name .
-The
+function reads through the group database to retrieve the supplementary groups
+for the user specified in
+.Fa name ,
+and returns the effective group list, whose first group is the value of
+.Fa basegid
+and the others are the retrieved supplementary groups.
.Fa basegid
-is automatically included in the groups list.
-Typically this value is given as
-the group number from the password file.
+typically is the user's group number from the password database.
.Pp
-The resulting group list is returned in the array pointed to by
+The effective group list is returned in the array pointed to by
.Fa groups .
The caller specifies the size of the
.Fa groups
@@ -70,6 +78,7 @@ Here, the group array will be filled with as many groups as will fit.
group membership list
.El
.Sh SEE ALSO
+.Xr setcred 2 ,
.Xr setgroups 2 ,
.Xr initgroups 3
.Sh HISTORY
diff --git a/lib/libc/gen/getgrouplist.c b/lib/libc/gen/getgrouplist.c
index 5bd06bc5121f..9c57b7031336 100644
--- a/lib/libc/gen/getgrouplist.c
+++ b/lib/libc/gen/getgrouplist.c
@@ -29,13 +29,8 @@
* SUCH DAMAGE.
*/
-/*
- * get credential
- */
#include <sys/types.h>
-#include <grp.h>
-#include <string.h>
#include <unistd.h>
#include <ssp/ssp.h>
@@ -46,4 +41,3 @@ __ssp_real(getgrouplist)(const char *uname, gid_t agroup, gid_t *groups, int *gr
{
return __getgroupmembership(uname, agroup, groups, *grpcnt, grpcnt);
}
-
diff --git a/lib/libc/gen/initgroups.3 b/lib/libc/gen/initgroups.3
index 03bd07494fc9..4f538fb180ec 100644
--- a/lib/libc/gen/initgroups.3
+++ b/lib/libc/gen/initgroups.3
@@ -1,5 +1,13 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 2025 The FreeBSD Foundation
+.\"
+.\" Portions of this documentation were written by Olivier Certner
+.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD
+.\" Foundation.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -25,12 +33,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd October 26, 2014
+.Dd September 17, 2025
.Dt INITGROUPS 3
.Os
.Sh NAME
.Nm initgroups
-.Nd initialize group access list
+.Nd initialize supplementary groups as per the group database
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -40,19 +48,18 @@
.Sh DESCRIPTION
The
.Fn initgroups
-function
-uses the
-.Xr getgrouplist 3
-function to calculate the group access list for the user
-specified in
+function initializes the current process' supplementary groups as prescribed by
+its arguments and the system's group database.
+.Pp
+It first uses the
+.Fn getgrouplist
+function to compute a list of groups containing the passed
+.Fa basegid ,
+which typically is the user's initial numerical group ID from the password
+database, and the supplementary groups in the group database for the user named
.Fa name .
-This group list is then setup for the current process using
-.Xr setgroups 2 .
-The
-.Fa basegid
-is automatically included in the groups list.
-Typically this value is given as
-the group number from the password file.
+It then installs this list as the current process' supplementary groups using
+.Fn setgroups .
.Sh RETURN VALUES
.Rv -std initgroups
.Sh ERRORS
@@ -60,7 +67,7 @@ The
.Fn initgroups
function may fail and set
.Va errno
-for any of the errors specified for the library function
+to any of the errors specified for the library function
.Xr setgroups 2 .
It may also return:
.Bl -tag -width Er
@@ -77,3 +84,67 @@ The
.Fn initgroups
function appeared in
.Bx 4.2 .
+.Pp
+The
+.Fn initgroups
+function changed semantics in
+.Fx 15 ,
+following that of
+.Xr setgroups 2
+in the same release.
+Before that, it would also set the effective group ID to
+.Fa basegid ,
+and would not include the latter in the supplementary groups except before
+.Fx 8 .
+Its current behavior in these respects is known to be compatible with that of
+the following systems up to the specified versions that are current at time of
+this writing:
+.Bl -dash -width "-" -compact
+.It
+Linux (up to 6.6) with the GNU libc (up to 2.42)
+.It
+.Nx 1.1 and greater (up to 10)
+.It
+.Ox (up to 7.7)
+.It
+Systems based on illumos (up to August 2025 sources)
+.El
+.Sh SECURITY CONSIDERATIONS
+As
+.Fa basegid
+is typically the user's initial numerical group ID, to which the current
+process' effective group ID is generally initialized, processes using functions
+to change their effective group ID
+.Pq via Xr setgid 2 or similar
+or that are spawned from executables with the set-group-ID mode bit set will not
+be able to relinquish the access rights deriving from being a member of
+.Fa basegid ,
+as these functions do not change the supplementary groups.
+.Pp
+This behavior is generally desirable in order to paper over the difference of
+treatment between the effective group and supplementary ones in this situation,
+as they are all in the end indiscriminately used in traditional UNIX
+discretionary access checks.
+It blends well with the practice of allocating each user its own private group,
+as processes launched from a set-group-ID executable keep the same user and
+consistently stay also in the same user's group.
+Finally, it was also chosen for compatibility with other systems
+.Po
+see the
+.Sx HISTORY
+section
+.Pc .
+.Pp
+This convention of including
+.Fa basegid
+in the supplementary groups is however only enforced by the
+.Fn initgroups
+function, and not by the
+.Xr setgroups 2
+system call, so applications expressly wanting to include in the supplementary
+groups only those specified by the group database can themselves call
+.Fn getgrouplist
+and then
+.Fn setgroups
+on the result with the first element skipped
+.Pq see Xr getgrouplist 3 .
diff --git a/lib/libc/gen/initgroups.c b/lib/libc/gen/initgroups.c
index b6697dd7ed8f..a1a7d92250e2 100644
--- a/lib/libc/gen/initgroups.c
+++ b/lib/libc/gen/initgroups.c
@@ -3,6 +3,11 @@
*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2025 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Olivier Certner
+ * <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD
+ * Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,34 +34,52 @@
* SUCH DAMAGE.
*/
-#include <sys/param.h>
+/* For __sym_compat(). */
+#include <sys/cdefs.h>
-#include "namespace.h"
-#include <err.h>
-#include "un-namespace.h"
#include <errno.h>
-#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-int
-initgroups(const char *uname, gid_t agroup)
+/* For freebsd14_setgroups(). */
+#include "gen-compat.h"
+
+static int
+initgroups_impl(const char *uname, gid_t agroup,
+ int (*setgroups)(int, const gid_t *))
{
- int ngroups, ret;
- long ngroups_max;
gid_t *groups;
+ long ngroups_max;
+ int ngroups, ret;
/*
- * Provide space for one group more than possible to allow
- * setgroups to fail and set errno.
+ * Provide space for one group more than possible to allow setgroups()
+ * to fail and set 'errno' in case we get back more than {NGROUPS_MAX} +
+ * 1 groups.
*/
ngroups_max = sysconf(_SC_NGROUPS_MAX) + 2;
- if ((groups = malloc(sizeof(*groups) * ngroups_max)) == NULL)
- return (ENOMEM);
+ groups = malloc(sizeof(*groups) * ngroups_max);
+ if (groups == NULL)
+ return (-1); /* malloc() set 'errno'. */
ngroups = (int)ngroups_max;
- getgrouplist(uname, agroup, groups, &ngroups);
- ret = setgroups(ngroups, groups);
+ (void)getgrouplist(uname, agroup, groups, &ngroups);
+ ret = (*setgroups)(ngroups, groups);
+
free(groups);
- return (ret);
+ return (ret); /* setgroups() set 'errno'. */
}
+
+int
+initgroups(const char *uname, gid_t agroup)
+{
+ return (initgroups_impl(uname, agroup, setgroups));
+}
+
+int
+freebsd14_initgroups(const char *uname, gid_t agroup)
+{
+ return (initgroups_impl(uname, agroup, freebsd14_setgroups));
+}
+
+__sym_compat(initgroups, freebsd14_initgroups, FBSD_1.0);
diff --git a/lib/libc/gen/psignal.3 b/lib/libc/gen/psignal.3
index 098b7b02a9b9..bf6a99b4b113 100644
--- a/lib/libc/gen/psignal.3
+++ b/lib/libc/gen/psignal.3
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 10, 2025
+.Dd September 23, 2025
.Dt PSIGNAL 3
.Os
.Sh NAME
@@ -141,6 +141,13 @@ The name in
can be either the name of the signal, with or without the
.Dq SIG
prefix, or a decimal number.
+.Sh RETURN VALUES
+The
+.Fn sig2str
+and
+.Fn str2sig
+return 0 on success and -1 on translation failure.
+In the latter case the memory to store the translation result is left intact.
.Sh SEE ALSO
.Xr sigaction 2 ,
.Xr perror 3 ,
diff --git a/lib/libc/gen/sysconf.c b/lib/libc/gen/sysconf.c
index 66562d0e29f0..b5b732eed05d 100644
--- a/lib/libc/gen/sysconf.c
+++ b/lib/libc/gen/sysconf.c
@@ -51,7 +51,7 @@
#include "un-namespace.h"
#include "../stdlib/atexit.h"
-#include "tzdir.h" /* from ../../../contrib/tzcode/stdtime */
+#include "tzdir.h" /* from ../../../contrib/tzcode */
#include "libc_private.h"
#define _PATH_ZONEINFO TZDIR /* from tzfile.h */
diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h
index 97f22607ddd7..630ffe7daae3 100644
--- a/lib/libc/include/compat.h
+++ b/lib/libc/include/compat.h
@@ -80,4 +80,3 @@ __sym_compat(setgroups, freebsd14_setgroups, FBSD_1.0);
#undef __weak_reference
#endif /* __LIBC_COMPAT_H__ */
-
diff --git a/lib/libc/rpc/rpc_generic.c b/lib/libc/rpc/rpc_generic.c
index 0e563f6a5996..8019f2d8f236 100644
--- a/lib/libc/rpc/rpc_generic.c
+++ b/lib/libc/rpc/rpc_generic.c
@@ -610,6 +610,10 @@ __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
return NULL;
break;
#endif
+ case AF_NETLINK:
+ if (asprintf(&ret, "%s", (char *)nbuf->buf) < 0)
+ return NULL;
+ break;
case AF_LOCAL:
sun = nbuf->buf;
if (asprintf(&ret, "%.*s", (int)(sun->sun_len -
diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc
index 647cbe6f40ba..1baa39a6c0a6 100644
--- a/lib/libc/stdtime/Makefile.inc
+++ b/lib/libc/stdtime/Makefile.inc
@@ -32,4 +32,5 @@ MLINKS+=strftime.3 strftime_l.3
MLINKS+=strptime.3 strptime_l.3
MLINKS+=time2posix.3 posix2time.3
MLINKS+=tzset.3 daylight.3 \
- tzset.3 timezone.3
+ tzset.3 timezone.3 \
+ tzset.3 tzname.3
diff --git a/lib/libc/stdtime/ctime.3 b/lib/libc/stdtime/ctime.3
index 96b7f775535a..6384e8bd959b 100644
--- a/lib/libc/stdtime/ctime.3
+++ b/lib/libc/stdtime/ctime.3
@@ -27,7 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd March 26, 2024
+.Dd September 23, 2025
.Dt CTIME 3
.Os
.Sh NAME
@@ -41,6 +41,8 @@
.Nm localtime ,
.Nm localtime_r ,
.Nm mktime ,
+.Nm offtime ,
+.Nm offtime_r ,
.Nm timegm
.Nd transform binary date and time values
.Sh LIBRARY
@@ -68,14 +70,19 @@
.Fn localtime_r "const time_t *clock" "struct tm *result"
.Ft time_t
.Fn mktime "struct tm *tm"
+.Ft struct tm *
+.Fn offtime "const time_t *clock" "long offset"
+.Ft struct tm *
+.Fn offtime_r "const time_t *clock" "long offset" "struct tm *result"
.Ft time_t
.Fn timegm "struct tm *tm"
.Sh DESCRIPTION
The
.Fn ctime ,
.Fn gmtime ,
+.Fn localtime ,
and
-.Fn localtime
+.Fn offtime
functions all take as argument a pointer to a time value representing
the time in seconds since the Epoch (00:00:00 UTC on January 1, 1970;
see
@@ -123,6 +130,18 @@ adjustment, and returns a pointer to a
.Vt struct tm .
.Pp
The
+.Fn offtime
+function similarly converts the time value with a time zone adjustment
+corresponding to the provided
+.Fa offset ,
+which is expressed in seconds, with positive values indicating a time
+zone ahead of UTC (east of the Prime Meridian).
+It does not call
+.Xr tzset 3
+or modify
+.Va tzname .
+.Pp
+The
.Fn ctime
function
adjusts the time value for the current time zone in the same manner as
@@ -155,13 +174,15 @@ except the caller must provide the output buffer
.Fa buf ,
which must be at least 26 characters long, to store the result in.
The
-.Fn localtime_r
+.Fn localtime_r ,
+.Fn gmtime_r ,
and
-.Fn gmtime_r
+.Fn offtime_r
functions provide the same functionality as
-.Fn localtime
+.Fn localtime ,
+.Fn gmtime ,
and
-.Fn gmtime
+.Fn offtime
respectively, except the caller must provide the output buffer
.Fa result .
.Pp
@@ -368,6 +389,12 @@ and
.Fn localtime_r
functions have been available since
.Fx 8.0 .
+The
+.Fn offtime
+and
+.Fn offtime_r
+functions were added in
+.Fx 15.0 .
.Sh BUGS
Except for
.Fn difftime ,
diff --git a/lib/libc/stdtime/tzset.3 b/lib/libc/stdtime/tzset.3
index 94ccbec9aba7..33e6a556306d 100644
--- a/lib/libc/stdtime/tzset.3
+++ b/lib/libc/stdtime/tzset.3
@@ -28,7 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 25, 2023
+.Dd September 30, 2025
.Dt TZSET 3
.Os
.Sh NAME
@@ -58,8 +58,8 @@ specifies how this is done.
.Pp
If
.Ev TZ
-does not appear in the environment, the best available approximation to
-local wall clock time, as specified by the
+does not appear in the environment, the best available approximation
+to local wall clock time, as specified by the
.Xr tzfile 5 Ns -format
file
.Pa /etc/localtime
@@ -68,9 +68,7 @@ is used.
If
.Ev TZ
appears in the environment but its value is a null string, Coordinated
-Universal Time
-.Pq Tn UTC
-is used (without leap second correction).
+Universal Time (UTC) is used (without leap second correction).
.Pp
If
.Ev TZ
@@ -81,13 +79,12 @@ the rest of its value is used as a pathname of a
file from which to read the time conversion information.
If the first character of the pathname is a slash
.Pq Ql /
-it is used as
-an absolute pathname; otherwise, it is used as a pathname relative to
-the system time conversion information directory.
+it is used as an absolute pathname; otherwise, it is used as a
+pathname relative to the system time conversion information directory.
.Pp
-If its value does not begin with a colon, it is first used as the pathname
-of a file (as described above) from which to read the time conversion
-information.
+If its value does not begin with a colon, it is first used as the
+pathname of a file (as described above) from which to read the time
+conversion information.
If that file cannot be read, the value is then interpreted as a direct
specification (the format is described below) of the time conversion
information.
@@ -96,24 +93,23 @@ If the
.Ev TZ
environment variable does not specify a
.Xr tzfile 5 Ns -format
-file and cannot be interpreted as a direct specification,
-.Tn UTC
-is used.
+file and cannot be interpreted as a direct specification, UTC is used.
.Pp
After the first call to
.Nm tzset ,
the
.Vt timezone
-variable is set to the difference, in seconds, between Coordinated Universal
-Time (UTC) and the local time.
+variable is set to the difference, in seconds, between Coordinated
+Universal Time (UTC) and the local time.
The
.Vt daylight
variable is set to 0 if the local timezone is observing standard time.
-It is set to 1 if the local timezone ever observes an alternate time, such as summer time.
+It is set to 1 if the local timezone ever observes an alternate time,
+such as summer time.
The first element of the
.Vt tzname
-array is the timezone name of standard time, while the second element is the
-name of the altnerative time zone.
+array is the timezone name of standard time, while the second element
+is the name of the altnerative time zone.
.Sh SPECIFICATION FORMAT
When
.Ev TZ
@@ -151,8 +147,7 @@ minus
.Pq Ql \- ,
plus
.Pq Ql + ,
-and
-.Tn ASCII
+and ASCII
.Dv NUL
are allowed.
.It Em offset
@@ -294,10 +289,8 @@ by the
file
.Em posixrules
in the system time conversion information directory are used, with the
-standard and summer time offsets from
-.Tn UTC
-replaced by those specified by
-the
+standard and summer time offsets from UTC replaced by those specified
+by the
.Em offset
values in
.Ev TZ .
@@ -315,20 +308,14 @@ local time zone file
.It Pa /usr/share/zoneinfo
time zone directory
.It Pa /usr/share/zoneinfo/posixrules
-rules for
-.Tn POSIX Ns -style
-.Tn TZ Ns 's
+rules for POSIX-style TZs
.It Pa /usr/share/zoneinfo/Etc/GMT
-for
-.Tn UTC
-leap seconds
+for UTC leap seconds
.El
.Pp
If the file
.Pa /usr/share/zoneinfo/UTC
-does not exist,
-.Tn UTC
-leap seconds are loaded from
+does not exist, UTC leap seconds are loaded from
.Pa /usr/share/zoneinfo/posixrules .
.Sh SEE ALSO
.Xr date 1 ,
diff --git a/lib/libc/tests/stdio/printfloat_test.c b/lib/libc/tests/stdio/printfloat_test.c
index 031859124163..4493fe1c15d3 100644
--- a/lib/libc/tests/stdio/printfloat_test.c
+++ b/lib/libc/tests/stdio/printfloat_test.c
@@ -398,6 +398,18 @@ ATF_TC_BODY(subnormal_float, tc)
testfmt("-0X1P-149", "%A", negative);
}
+ATF_TC_WITHOUT_HEAD(hexadecimal_rounding_fullprec);
+ATF_TC_BODY(hexadecimal_rounding_fullprec, tc)
+{
+ /* Double: %.13a with binary64 mantissa=53 */
+ testfmt("0x1.1234567890bbbp+0", "%.13a", 0x1.1234567890bbbp+0);
+
+#if defined(__aarch64__)
+ /* On arm64, long double is IEEE binary128 (mantissa=113) */
+ testfmt("0x1.3c0ca428c59fbbbbbbbbbbbbbbbbp+0", "%.28La", 0x1.3c0ca428c59fbbbbbbbbbbbbbbbbp+0L);
+#endif
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -414,6 +426,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, hexadecimal_rounding);
ATF_TP_ADD_TC(tp, subnormal_double);
ATF_TP_ADD_TC(tp, subnormal_float);
+ ATF_TP_ADD_TC(tp, hexadecimal_rounding_fullprec);
return (atf_no_error());
}
diff --git a/lib/libc/tests/stdtime/Makefile b/lib/libc/tests/stdtime/Makefile
index 6b9068e1641b..590dea22da31 100644
--- a/lib/libc/tests/stdtime/Makefile
+++ b/lib/libc/tests/stdtime/Makefile
@@ -3,6 +3,7 @@
ATF_TESTS_C+= strptime_test
ATF_TESTS_C+= detect_tz_changes_test
+CFLAGS.detect_tz_changes_test+= -I${SRCTOP}/contrib/tzcode
.if ${MK_DETECT_TZ_CHANGES} != "no"
CFLAGS.detect_tz_changes_test+= -DDETECT_TZ_CHANGES
.endif
diff --git a/lib/libc/tests/stdtime/detect_tz_changes_test.c b/lib/libc/tests/stdtime/detect_tz_changes_test.c
index 6648d8498cc5..06c31c9fbc3d 100644
--- a/lib/libc/tests/stdtime/detect_tz_changes_test.c
+++ b/lib/libc/tests/stdtime/detect_tz_changes_test.c
@@ -20,12 +20,16 @@
#include <time.h>
#include <unistd.h>
+#include "tzdir.h"
+
#include <atf-c.h>
-static const struct tzcase {
+struct tzcase {
const char *tzfn;
const char *expect;
-} tzcases[] = {
+};
+
+static const struct tzcase tzcases[] = {
/*
* A handful of time zones and the expected result of
* strftime("%z (%Z)", tm) when that time zone is active
@@ -41,7 +45,8 @@ static const struct tzcase {
{ "UTC", "+0000 (UTC)" },
{ 0 },
};
-
+static const struct tzcase utc = { "UTC", "+0000 (UTC)" };
+static const struct tzcase invalid = { "invalid", "+0000 (-00)" };
static const time_t then = 1751328000; /* 2025-07-01 00:00:00 UTC */
static bool debugging;
@@ -62,9 +67,9 @@ debug(const char *fmt, ...)
static void
change_tz(const char *tzn)
{
- static const char *zfn = "/usr/share/zoneinfo";
- static const char *tfn = "root/etc/.localtime";
- static const char *dfn = "root/etc/localtime";
+ static const char *zfn = TZDIR;
+ static const char *tfn = "root" TZDEFAULT ".tmp";
+ static const char *dfn = "root" TZDEFAULT;
ssize_t clen;
int zfd, sfd, dfd;
@@ -96,6 +101,50 @@ test_tz(const char *expect)
ATF_CHECK_STREQ(expect, buf);
}
+ATF_TC(tz_default);
+ATF_TC_HEAD(tz_default, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test default zone");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(tz_default, tc)
+{
+ /* prepare chroot with no /etc/localtime */
+ ATF_REQUIRE_EQ(0, mkdir("root", 0755));
+ ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755));
+ /* enter chroot */
+ ATF_REQUIRE_EQ(0, chroot("root"));
+ ATF_REQUIRE_EQ(0, chdir("/"));
+ /* check timezone */
+ unsetenv("TZ");
+ test_tz("+0000 (UTC)");
+}
+
+ATF_TC(tz_invalid_file);
+ATF_TC_HEAD(tz_invalid_file, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test invalid zone file");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(tz_invalid_file, tc)
+{
+ static const char *dfn = "root/etc/localtime";
+ int fd;
+
+ /* prepare chroot with bogus /etc/localtime */
+ ATF_REQUIRE_EQ(0, mkdir("root", 0755));
+ ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755));
+ ATF_REQUIRE((fd = open(dfn, O_RDWR | O_CREAT, 0644)) >= 0);
+ ATF_REQUIRE_EQ(8, write(fd, "invalid\n", 8));
+ ATF_REQUIRE_EQ(0, close(fd));
+ /* enter chroot */
+ ATF_REQUIRE_EQ(0, chroot("root"));
+ ATF_REQUIRE_EQ(0, chdir("/"));
+ /* check timezone */
+ unsetenv("TZ");
+ test_tz(invalid.expect);
+}
+
ATF_TC(thin_jail);
ATF_TC_HEAD(thin_jail, tc)
{
@@ -320,6 +369,30 @@ test_tz_env(const char *tzval, const char *expect)
test_tz(expect);
}
+static void
+tz_env_common(void)
+{
+ char path[MAXPATHLEN];
+ const struct tzcase *tzcase = tzcases;
+ int len;
+
+ /* relative path */
+ for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++)
+ test_tz_env(tzcase->tzfn, tzcase->expect);
+ /* absolute path */
+ for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) {
+ len = snprintf(path, sizeof(path), "%s/%s", TZDIR, tzcase->tzfn);
+ ATF_REQUIRE(len > 0 && (size_t)len < sizeof(path));
+ test_tz_env(path, tzcase->expect);
+ }
+ /* absolute path with additional slashes */
+ for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) {
+ len = snprintf(path, sizeof(path), "%s/////%s", TZDIR, tzcase->tzfn);
+ ATF_REQUIRE(len > 0 && (size_t)len < sizeof(path));
+ test_tz_env(path, tzcase->expect);
+ }
+}
+
ATF_TC(tz_env);
ATF_TC_HEAD(tz_env, tc)
{
@@ -327,10 +400,22 @@ ATF_TC_HEAD(tz_env, tc)
}
ATF_TC_BODY(tz_env, tc)
{
- const struct tzcase *tzcase;
+ tz_env_common();
+ /* escape from TZDIR is permitted when not setugid */
+ test_tz_env("../zoneinfo/UTC", utc.expect);
+}
- for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++)
- test_tz_env(tzcase->tzfn, tzcase->expect);
+
+ATF_TC(tz_invalid_env);
+ATF_TC_HEAD(tz_invalid_env, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test invalid TZ value");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(tz_invalid_env, tc)
+{
+ test_tz_env("invalid", invalid.expect);
+ test_tz_env(":invalid", invalid.expect);
}
ATF_TC(setugid);
@@ -367,23 +452,25 @@ ATF_TC_HEAD(tz_env_setugid, tc)
}
ATF_TC_BODY(tz_env_setugid, tc)
{
- const struct tzcase *tzcase = tzcases;
-
ATF_REQUIRE_EQ(0, seteuid(UID_NOBODY));
ATF_REQUIRE(issetugid());
- for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++)
- test_tz_env(tzcase->tzfn, tzcase->expect);
+ tz_env_common();
+ /* escape from TZDIR is not permitted when setugid */
+ test_tz_env("../zoneinfo/UTC", invalid.expect);
}
ATF_TP_ADD_TCS(tp)
{
debugging = !getenv("__RUNNING_INSIDE_ATF_RUN") &&
isatty(STDERR_FILENO);
+ ATF_TP_ADD_TC(tp, tz_default);
+ ATF_TP_ADD_TC(tp, tz_invalid_file);
ATF_TP_ADD_TC(tp, thin_jail);
#ifdef DETECT_TZ_CHANGES
ATF_TP_ADD_TC(tp, detect_tz_changes);
#endif /* DETECT_TZ_CHANGES */
ATF_TP_ADD_TC(tp, tz_env);
+ ATF_TP_ADD_TC(tp, tz_invalid_env);
ATF_TP_ADD_TC(tp, setugid);
ATF_TP_ADD_TC(tp, tz_env_setugid);
return (atf_no_error());
diff --git a/lib/libc/tests/string/memcmp_test.c b/lib/libc/tests/string/memcmp_test.c
index 5286a0b994f3..fa2f498ccfaf 100644
--- a/lib/libc/tests/string/memcmp_test.c
+++ b/lib/libc/tests/string/memcmp_test.c
@@ -41,14 +41,14 @@
#endif
/*
- * On FreeBSD we demand that memcmp returns the difference between the
- * characters at the first site of mismatch. However, ISO/IEC 9899:1990
- * only specifies that a number greater than, equal to, or less than
- * zero shall be returned. If a unit test for this less strict
- * behaviour is desired, define RES(x) to be (((x) > 0) - ((x) < 0)).
+ * On FreeBSD we previously demanded that memcmp returns the difference
+ * between the characters at the first site of mismatch. However,
+ * ISO/IEC 9899:1990 only specifies that a number greater than, equal
+ * to, or less than zero shall be returned. If a unit test for the
+ * more strict behaviour is desired, define RES(x) to be (x).
*/
#ifndef RES
-#define RES(x) (x)
+#define RES(x) (((x) > 0) - ((x) < 0))
#endif
static int (*memcmp_fn)(const void *, const void *, size_t);
diff --git a/lib/libc/tests/tls/dso/Makefile b/lib/libc/tests/tls/dso/Makefile
index 5efd8b29a6bd..783534ff7aae 100644
--- a/lib/libc/tests/tls/dso/Makefile
+++ b/lib/libc/tests/tls/dso/Makefile
@@ -6,6 +6,7 @@ SRCS= h_tls_dlopen.c
MAN=
PACKAGE= tests
+NO_DEV_PACKAGE=
LIBDIR= ${TESTSBASE}/lib/libc/tls
SHLIB_MAJOR= 1
diff --git a/lib/libc/tests/tls_dso/Makefile b/lib/libc/tests/tls_dso/Makefile
index 89296c643695..7cb8f98b431e 100644
--- a/lib/libc/tests/tls_dso/Makefile
+++ b/lib/libc/tests/tls_dso/Makefile
@@ -7,6 +7,7 @@ LIBDIR= ${TESTSBASE}/lib/libc/tls
SHLIBDIR= ${TESTSBASE}/lib/libc/tls
SHLIB_MAJOR= 1
PACKAGE= tests
+NO_DEV_PACKAGE=
WITHOUT_STATIC=
WITHOUT_PROFILE=
diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile
index f0254c1f42bc..c7a54253dae9 100644
--- a/lib/libedit/Makefile
+++ b/lib/libedit/Makefile
@@ -1,7 +1,5 @@
# $NetBSD: Makefile,v 1.56 2016/03/02 19:24:20 christos Exp $
-PACKAGE=clibs
-
EDITDIR= ${SRCTOP}/contrib/libedit
.PATH: ${EDITDIR}
@@ -93,6 +91,7 @@ tc1.o: ${EDITDIR}/TEST/tc1.c
test: tc1.o libedit.a ${DPADD} ${LIBTERMCAP}
${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD}
+.include "Makefile.inc"
.include <bsd.lib.mk>
CWARNFLAGS.chartype.c= ${NO_WUSE_AFTER_FREE}
diff --git a/lib/libedit/Makefile.inc b/lib/libedit/Makefile.inc
new file mode 100644
index 000000000000..9ec65b0d266f
--- /dev/null
+++ b/lib/libedit/Makefile.inc
@@ -0,0 +1 @@
+PACKAGE?=runtime
diff --git a/lib/libexpat/expat_config.h b/lib/libexpat/expat_config.h
index 748f75ee157d..565404f1577b 100644
--- a/lib/libexpat/expat_config.h
+++ b/lib/libexpat/expat_config.h
@@ -31,7 +31,7 @@
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
-/* Define to 1 if you have the `getpagesize' function. */
+/* Define to 1 if you have the 'getpagesize' function. */
#define HAVE_GETPAGESIZE 1
/* Define to 1 if you have the `getrandom' function. */
@@ -40,10 +40,10 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
-/* Define to 1 if you have the `bsd' library (-lbsd). */
+/* Define to 1 if you have the 'bsd' library (-lbsd). */
/* #undef HAVE_LIBBSD */
-/* Define to 1 if you have a working `mmap' system call. */
+/* Define to 1 if you have a working 'mmap' system call. */
#define HAVE_MMAP 1
/* Define to 1 if you have the <stdint.h> header file. */
@@ -89,7 +89,7 @@
#define PACKAGE_NAME "expat"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "expat 2.7.1"
+#define PACKAGE_STRING "expat 2.7.3"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "expat"
@@ -98,15 +98,15 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.7.1"
+#define PACKAGE_VERSION "2.7.3"
-/* Define to 1 if all of the C90 standard headers exist (not just the ones
+/* Define to 1 if all of the C89 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#define STDC_HEADERS 1
/* Version number of package */
-#define VERSION "2.7.1"
+#define VERSION "2.7.3"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
@@ -140,10 +140,10 @@
/* Define to make XML Namespaces functionality available. */
#define XML_NS 1
-/* Define to empty if `const' does not conform to ANSI C. */
+/* Define to empty if 'const' does not conform to ANSI C. */
/* #undef const */
-/* Define to `long int' if <sys/types.h> does not define. */
+/* Define to 'long int' if <sys/types.h> does not define. */
/* #undef off_t */
#endif // ndef EXPAT_CONFIG_H
diff --git a/lib/libexpat/libbsdxml.3 b/lib/libexpat/libbsdxml.3
index c91184840b70..d25249bbc155 100644
--- a/lib/libexpat/libbsdxml.3
+++ b/lib/libexpat/libbsdxml.3
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"/
-.Dd April 7, 2025
+.Dd September 28, 2025
.Dt LIBBSDXML 3
.Os
.Sh NAME
@@ -34,7 +34,7 @@
.Sh DESCRIPTION
The
.Nm
-library is a verbatim copy of the eXpat XML library version 2.7.1.
+library is a verbatim copy of the eXpat XML library version 2.7.3.
.Pp
The
.Nm
diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c
index 931391055919..ad3348af0d2d 100644
--- a/lib/libjail/jail.c
+++ b/lib/libjail/jail.c
@@ -95,8 +95,8 @@ jail_setv(int flags, ...)
goto error;
if (jailparam_import(jp + njp, value) < 0)
goto error;
- if (!strcmp(name, "desc")
- && (flags & (JAIL_GET_DESC | JAIL_OWN_DESC))) {
+ if (!strcmp(name, "desc") &&
+ (flags & (JAIL_GET_DESC | JAIL_OWN_DESC))) {
jp_desc = jp + njp;
desc_value = value;
}
@@ -145,8 +145,8 @@ jail_getv(int flags, ...)
va_end(tap);
goto error;
}
- if (!strcmp(jp[njp].jp_name, "desc")
- && (flags & (JAIL_USE_DESC | JAIL_AT_DESC))) {
+ if (!strcmp(jp[njp].jp_name, "desc") &&
+ (flags & (JAIL_USE_DESC | JAIL_AT_DESC))) {
jp_desc = jp + njp;
desc_value = value;
} else if (!strcmp(jp[njp].jp_name, "lastjid")) {
@@ -181,8 +181,8 @@ jail_getv(int flags, ...)
}
if (jailparam_import(jp_key, key_value) < 0)
goto error;
- if (jp_desc != NULL && jp_desc != jp_key
- && jailparam_import(jp_desc, desc_value) < 0)
+ if (jp_desc != NULL && jp_desc != jp_key &&
+ jailparam_import(jp_desc, desc_value) < 0)
goto error;
/* Get the jail and export the parameters. */
jid = jailparam_get(jp, njp, flags);
@@ -604,8 +604,8 @@ jailparam_get(struct jailparam *jp, unsigned njp, int flags)
jp_desc = jp_lastjid = jp_jid = jp_name = NULL;
arrays = 0;
for (ai = j = 0; j < njp; j++) {
- if (!strcmp(jp[j].jp_name, "desc")
- && (flags & (JAIL_USE_DESC | JAIL_AT_DESC)))
+ if (!strcmp(jp[j].jp_name, "desc") &&
+ (flags & (JAIL_USE_DESC | JAIL_AT_DESC)))
jp_desc = jp + j;
else if (!strcmp(jp[j].jp_name, "lastjid"))
jp_lastjid = jp + j;
@@ -920,13 +920,21 @@ jailparam_type(struct jailparam *jp)
} desc;
int mib[CTL_MAXNAME];
- /* The "lastjid" parameter isn't real. */
+ /*
+ * Some pseudo-parameters don't show up in the sysctl
+ * parameter list.
+ */
name = jp->jp_name;
if (!strcmp(name, "lastjid")) {
jp->jp_valuelen = sizeof(int);
jp->jp_ctltype = CTLTYPE_INT | CTLFLAG_WR;
return (0);
}
+ if (!strcmp(name, "desc")) {
+ jp->jp_valuelen = sizeof(int);
+ jp->jp_ctltype = CTLTYPE_INT | CTLFLAG_RW;
+ return (0);
+ }
/* Find the sysctl that describes the parameter. */
mib[0] = 0;
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c
index b2b7c6ecce56..fed483978e62 100644
--- a/lib/libkvm/kvm_proc.c
+++ b/lib/libkvm/kvm_proc.c
@@ -150,13 +150,14 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
kp->ki_cr_flags = 0;
if (ucred.cr_flags & CRED_FLAG_CAPMODE)
kp->ki_cr_flags |= KI_CRF_CAPABILITY_MODE;
- if (ucred.cr_ngroups > KI_NGROUPS) {
+ if (1 + ucred.cr_ngroups > KI_NGROUPS) {
kp->ki_ngroups = KI_NGROUPS;
kp->ki_cr_flags |= KI_CRF_GRP_OVERFLOW;
} else
- kp->ki_ngroups = ucred.cr_ngroups;
- kvm_read(kd, (u_long)ucred.cr_groups, kp->ki_groups,
- kp->ki_ngroups * sizeof(gid_t));
+ kp->ki_ngroups = 1 + ucred.cr_ngroups;
+ kp->ki_groups[0] = ucred.cr_gid;
+ kvm_read(kd, (u_long)ucred.cr_groups, kp->ki_groups + 1,
+ (kp->ki_ngroups - 1) * sizeof(gid_t));
if (ucred.cr_prison != NULL) {
if (KREAD(kd, (u_long)ucred.cr_prison, &pr)) {
_kvm_err(kd, kd->program,
diff --git a/lib/liblzma/Makefile b/lib/liblzma/Makefile
index 27e0521f5884..9c6ece74ffd0 100644
--- a/lib/liblzma/Makefile
+++ b/lib/liblzma/Makefile
@@ -1,4 +1,6 @@
-PACKAGE=lib${LIB}
+PACKAGE= xz
+LIB_PACKAGE=
+
LIB= lzma
LZMADIR= ${SRCTOP}/contrib/xz/src/liblzma
diff --git a/lib/libmixer/Makefile b/lib/libmixer/Makefile
index a0bb37a85fb8..49621ad1f188 100644
--- a/lib/libmixer/Makefile
+++ b/lib/libmixer/Makefile
@@ -1,3 +1,5 @@
+PACKAGE= sound
+
LIB= mixer
SRCS= ${LIB}.c
INCS= ${LIB}.h
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index 190ee46baf21..8c4b26b98054 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -391,6 +391,8 @@ static const struct snl_attr_parser ap_getstatus[] = {
{ .type = PF_GS_CHKSUM, .off = _OUT(pf_chksum), .arg_u32 = PF_MD5_DIGEST_LENGTH, .cb = snl_attr_get_bytes },
{ .type = PF_GS_BCOUNTERS, .off = _OUT(bcounters), .arg_u32 = 2 * 2, .cb = snl_attr_get_uint64_array },
{ .type = PF_GS_PCOUNTERS, .off = _OUT(pcounters), .arg_u32 = 2 * 2 * 2, .cb = snl_attr_get_uint64_array },
+ { .type = PF_GS_NCOUNTERS, .off = _OUT(ncounters), .cb = snl_attr_get_counters },
+ { .type = PF_GS_FRAGMENTS, .off = _OUT(fragments), .cb = snl_attr_get_uint64 },
};
SNL_DECLARE_PARSER(getstatus_parser, struct genlmsghdr, snl_f_p_empty, ap_getstatus);
#undef _OUT
@@ -429,6 +431,7 @@ pfctl_get_status_h(struct pfctl_handle *h)
TAILQ_INIT(&status->lcounters);
TAILQ_INIT(&status->fcounters);
TAILQ_INIT(&status->scounters);
+ TAILQ_INIT(&status->ncounters);
while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
if (! snl_parse_nlmsg(&h->ss, hdr, &getstatus_parser, status))
@@ -558,6 +561,10 @@ pfctl_free_status(struct pfctl_status *status)
free(c->name);
free(c);
}
+ TAILQ_FOREACH_SAFE(c, &status->ncounters, entry, tmp) {
+ free(c->name);
+ free(c);
+ }
free(status);
}
@@ -1696,6 +1703,7 @@ static struct snl_attr_parser ap_getrule[] = {
{ .type = PF_RT_MAX_PKT_SIZE, .off =_OUT(r.max_pkt_size), .cb = snl_attr_get_uint16 },
{ .type = PF_RT_TYPE_2, .off = _OUT(r.type), .cb = snl_attr_get_uint16 },
{ .type = PF_RT_CODE_2, .off = _OUT(r.code), .cb = snl_attr_get_uint16 },
+ { .type = PF_RT_EXPTIME, .off = _OUT(r.exptime), .cb = snl_attr_get_time_t },
};
#undef _OUT
SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, snl_f_p_empty, ap_getrule);
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index da16d5179ec0..5880e1a88371 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -62,6 +62,8 @@ struct pfctl_status {
struct pfctl_status_counters lcounters;
struct pfctl_status_counters fcounters;
struct pfctl_status_counters scounters;
+ struct pfctl_status_counters ncounters;
+ uint64_t fragments;
uint64_t pcounters[2][2][2];
uint64_t bcounters[2][2];
};
@@ -283,6 +285,8 @@ struct pfctl_rule {
struct pf_addr addr;
uint16_t port;
} divert;
+
+ time_t exptime;
};
TAILQ_HEAD(pfctl_rulequeue, pfctl_rule);
diff --git a/lib/libpmc/Makefile b/lib/libpmc/Makefile
index 8728b0c1c76d..590f719ebff4 100644
--- a/lib/libpmc/Makefile
+++ b/lib/libpmc/Makefile
@@ -1,5 +1,5 @@
-LIB_CXX= pmc
-
+PACKAGE=pmc
+LIB_CXX=pmc
SRCS= libpmc.c pmclog.c libpmc_pmu_util.c libpmc_json.cc
INCS= pmc.h pmclog.h pmcformat.h
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index 1651cbc6820f..df77cabcd36b 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -1973,6 +1973,7 @@ procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp)
struct ucred ucred;
gid_t *groups;
size_t len;
+ unsigned int ngroups;
assert(kd != NULL);
assert(kp != NULL);
@@ -1990,19 +1991,22 @@ procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp)
proc.p_ucred, kp->ki_pid);
return (NULL);
}
- len = ucred.cr_ngroups * sizeof(gid_t);
+ ngroups = 1 + ucred.cr_ngroups;
+ len = ngroups * sizeof(gid_t);
groups = malloc(len);
if (groups == NULL) {
warn("malloc(%zu)", len);
return (NULL);
}
- if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups, len)) {
+ groups[0] = ucred.cr_gid;
+ if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups + 1,
+ len - sizeof(gid_t))) {
warnx("can't read groups at %p for pid %d",
ucred.cr_groups, kp->ki_pid);
free(groups);
return (NULL);
}
- *cntp = ucred.cr_ngroups;
+ *cntp = ngroups;
return (groups);
}
diff --git a/lib/libsamplerate/Makefile b/lib/libsamplerate/Makefile
index 256f2087284f..4c55d5c2cb82 100644
--- a/lib/libsamplerate/Makefile
+++ b/lib/libsamplerate/Makefile
@@ -1,7 +1,9 @@
.PATH: ${SRCTOP}/contrib/libsamplerate
+PACKAGE= sound
+
LIB= samplerate
-INTERNALLIB=
+PRIVATELIB=
SRCS= samplerate.c \
src_linear.c \
diff --git a/lib/libsdp/Makefile b/lib/libsdp/Makefile
index f0153e756dfd..8177c9bdbd1a 100644
--- a/lib/libsdp/Makefile
+++ b/lib/libsdp/Makefile
@@ -1,6 +1,7 @@
# $Id: Makefile,v 1.2 2003/09/07 20:34:19 max Exp $
-PACKAGE=lib${LIB}
+PACKAGE= bluetooth
+LIB_PACKAGE=
LIB= sdp
MAN= sdp.3
diff --git a/lib/libsdp/sdp.3 b/lib/libsdp/sdp.3
index dcd9077798ea..015f9cd8fb44 100644
--- a/lib/libsdp/sdp.3
+++ b/lib/libsdp/sdp.3
@@ -24,7 +24,7 @@
.\"
.\" $Id: sdp.3,v 1.1 2003/09/07 20:34:19 max Exp $
.\"
-.Dd April 30, 2018
+.Dd September 16, 2025
.Dt SDP 3
.Os
.Sh NAME
@@ -87,7 +87,7 @@
.Fn sdp_uuid2desc "uint16_t uuid"
.Ft int32_t
.Fo sdp_register_service
-.Fa "void *xss" "uint16_t uuid" "bdaddr_p const bdaddr" "uint8_t const *data"
+.Fa "void *xss" "uint16_t uuid" "const bdaddr_t *bdaddr" "uint8_t const *data"
.Fa "uint32_t datalen" "uint32_t *handle"
.Fc
.Ft int32_t
diff --git a/lib/libsdp/sdp.h b/lib/libsdp/sdp.h
index faad36aefca6..0c9474a70eff 100644
--- a/lib/libsdp/sdp.h
+++ b/lib/libsdp/sdp.h
@@ -702,7 +702,7 @@ typedef struct sdp_panu_profile sdp_panu_profile_t;
typedef struct sdp_panu_profile * sdp_panu_profile_p;
int32_t sdp_register_service (void *xss, uint16_t uuid,
- bdaddr_p const bdaddr, uint8_t const *data,
+ const bdaddr_t *bdaddr, uint8_t const *data,
uint32_t datalen, uint32_t *handle);
int32_t sdp_unregister_service (void *xss, uint32_t handle);
int32_t sdp_change_service (void *xss, uint32_t handle,
diff --git a/lib/libsdp/service.c b/lib/libsdp/service.c
index 9f07d1ba86ba..2cce6c133600 100644
--- a/lib/libsdp/service.c
+++ b/lib/libsdp/service.c
@@ -45,7 +45,7 @@
static int32_t sdp_receive_error_pdu(sdp_session_p ss);
int32_t
-sdp_register_service(void *xss, uint16_t uuid, bdaddr_p const bdaddr,
+sdp_register_service(void *xss, uint16_t uuid, const bdaddr_t *bdaddr,
uint8_t const *data, uint32_t datalen, uint32_t *handle)
{
sdp_session_p ss = (sdp_session_p) xss;
diff --git a/lib/libstdbuf/Makefile b/lib/libstdbuf/Makefile
index 102c6745c593..9e289e0018fc 100644
--- a/lib/libstdbuf/Makefile
+++ b/lib/libstdbuf/Makefile
@@ -1,6 +1,5 @@
.include <bsd.own.mk>
-PACKAGE=lib${LIB}
LIB= stdbuf
SRCS= stdbuf.c
SHLIB_MAJOR= 1
diff --git a/lib/libstdthreads/Makefile b/lib/libstdthreads/Makefile
index 49d024052420..dcdac58efc12 100644
--- a/lib/libstdthreads/Makefile
+++ b/lib/libstdthreads/Makefile
@@ -1,4 +1,4 @@
-PACKAGE=lib${LIB}
+PACKAGE=runtime
LIB= stdthreads
SHLIB_MAJOR= 0
diff --git a/lib/libsys/Symbol.map b/lib/libsys/Symbol.map
index eb71c813ae86..ae12124ca210 100644
--- a/lib/libsys/Symbol.map
+++ b/lib/libsys/Symbol.map
@@ -4,10 +4,4 @@ FBSDprivate_1.0 {
__getosreldate;
__libsys_interposing_slot;
_elf_aux_info;
- freebsd11_fstat;
- freebsd11_fstatat;
- freebsd11_getfsstat;
- freebsd11_lstat;
- freebsd11_stat;
- freebsd11_statfs;
};
diff --git a/lib/libsys/getgroups.2 b/lib/libsys/getgroups.2
index 37c8fbad7215..4881a65d532e 100644
--- a/lib/libsys/getgroups.2
+++ b/lib/libsys/getgroups.2
@@ -1,5 +1,13 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 2025 The FreeBSD Foundation
+.\"
+.\" Portions of this documentation were written by Olivier Certner
+.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD
+.\" Foundation.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -25,12 +33,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd August 1, 2025
+.Dd September 17, 2025
.Dt GETGROUPS 2
.Os
.Sh NAME
.Nm getgroups
-.Nd get group access list
+.Nd get the calling process' supplementary groups
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -40,36 +48,39 @@
.Sh DESCRIPTION
The
.Fn getgroups
-system call
-gets the current supplementary groups of the user process and stores it in the
-array
-.Fa gidset .
-The
+system call gets the calling process' supplementary groups and stores them in
+the
+.Fa gidset
+array in strictly ascending order.
+The value of
.Fa gidsetlen
-argument
-indicates the number of entries that may be placed in
+indicates the maximum number of entries that may be placed in
.Fa gidset .
-The
-.Fn getgroups
-system call
-returns the actual number of groups returned in
-.Fa gidset .
-As many as {NGROUPS_MAX} values may be returned.
+.Pp
If
.Fa gidsetlen
is zero,
.Fn getgroups
-returns the number of supplementary group IDs associated with
-the calling process without modifying the array pointed to by
+returns the cardinal of the calling process' supplementary groups set and
+ignores argument
.Fa gidset .
.Pp
+No more than
+.Dv {NGROUPS_MAX}
+values may ever be returned.
The value of
.Dv {NGROUPS_MAX}
should be obtained using
.Xr sysconf 3
to avoid hard-coding it into the executable.
.Sh RETURN VALUES
-A successful call returns the number of groups in the group set.
+On success, the
+.Fn getgroups
+system call returns the cardinal of the supplementary groups set.
+It always succeeds if argument
+.Fa gidsetlen
+is zero.
+.Pp
A value of -1 indicates that an error occurred, and the error
code is stored in the global variable
.Va errno .
@@ -81,12 +92,12 @@ are:
.It Bq Er EINVAL
The argument
.Fa gidsetlen
-is smaller than the number of groups in the group set.
+is smaller than the number of supplementary groups
+.Pq but not zero .
.It Bq Er EFAULT
-The argument
+An invalid address was encountered while reading from the
.Fa gidset
-specifies
-an invalid address.
+array.
.El
.Sh SEE ALSO
.Xr setgroups 2 ,
@@ -96,16 +107,51 @@ an invalid address.
The
.Fn getgroups
system call conforms to
-.St -p1003.1-2008 .
+.St -p1003.1-2008
+with the additional properties that supplementary groups are reported in
+strictly ascending order and the returned size coincides with the cardinal of
+the set.
.Sh HISTORY
The
.Fn getgroups
system call appeared in
.Bx 4.2 .
.Pp
+Since
+.Fx 14.3 ,
+the
+.Fn getgroups
+system call has treated the supplementary groups as a set, reporting them in
+strictly ascending order and returning the cardinal of the set.
+.Pp
Before
.Fx 15.0 ,
the
.Fn getgroups
-system call always returned the effective group ID for the process as the first
+system call would additionally return the effective group ID as the first
element of the array, before the supplementary groups.
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn getgroups
+system call gets the supplementary groups set in the
+.Fa gidset
+array.
+In particular, as evoked in
+.Sx HISTORY ,
+it does not anymore retrieve the effective GID in the first slot of
+.Fa gidset .
+Programs should not make any assumption about which group is placed in the first
+slot of
+.Fa gidset
+other than it being the supplementary group with smallest GID.
+.Pp
+The effective GID is present in the supplementary groups set if and only if it
+was explicitly set as a supplementary group.
+The function
+.Fn initgroups
+enforces that, while the
+.Fn setgroups
+system call does not.
+Please consult the
+.Xr initgroups 3
+manual page for the rationale.
diff --git a/lib/libsys/jail.2 b/lib/libsys/jail.2
index a0f47cc61cb3..ee4e5b03d38e 100644
--- a/lib/libsys/jail.2
+++ b/lib/libsys/jail.2
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd September 4, 2025
+.Dd September 15, 2025
.Dt JAIL 2
.Os
.Sh NAME
@@ -340,31 +340,6 @@ work the same as
and
.Fn jail_remove ,
except that they operate on the jail referred to by the passed descriptor.
-.Pp
-Jail operations via descriptors can be done by processes that do not
-normally have permission to see or affect the jail,
-as long as they are allowed by the file permissions of the jail
-descriptor itself.
-These permissions can be changed by the descriptor owner via
-.Xr fchmod 2
-and
-.Xr fchown 2 .
-.Fn jail_get
-requires read permission,
-.Fn jail_set
-and
-.Fn jail_remove
-require write permission,
-and
-.Fn jail_attach
-requires execute permission.
-Also, use of a descriptor with the
-.Dv JAIL_AT_DESC
-flag requires execute permission.
-An owning descriptor is identified by the
-.Em sticky bit ,
-which may also be changed via
-.Xr fchmod 2 .
.Sh RETURN VALUES
If successful,
.Fn jail ,
@@ -402,31 +377,6 @@ The
system call
will fail if:
.Bl -tag -width Er
-.It Bq Er EBADF
-The
-.Va desc
-parameter does not refer to a valid jail descriptor,
-and either the
-.Dv JAIL_USE_DESC
-or
-.Dv JAIL_AT_DESC
-flag was set.
-.It Bq Er EACCES
-Write permission is denied on the jail descriptor in the
-.Va desc
-parameter,
-and the
-.Dv JAIL_USE_DESC
-flag was set.
-.It Bq Er EACCES
-Execute permission is denied on the jail descriptor in the
-.Va desc
-parameter,
-and either the
-.Dv JAIL_AT_DESC
-or
-.Dv JAIL_ATTACH
-flag was set.
.It Bq Er EPERM
This process is not allowed to create a jail, either because it is not
the super-user, or because it would exceed the jail's
@@ -514,33 +464,6 @@ The
system call
will fail if:
.Bl -tag -width Er
-.It Bq Er EBADF
-The
-.Va desc
-parameter does not refer to a valid jail descriptor,
-and either the
-.Dv JAIL_USE_DESC
-or
-.Dv JAIL_AT_DESC
-flag was set.
-.It Bq Er EACCES
-Read permission is denied on the jail descriptor in the
-.Va desc
-parameter,
-and the
-.Dv JAIL_USE_DESC
-flag was set.
-.It Bq Er EACCES
-Execute permission is denied on the jail descriptor in the
-.Va desc
-parameter,
-and the
-.Dv JAIL_AT_DESC
-flag was set.
-.It Bq Er EFAULT
-.Fa Iov ,
-or one of the addresses contained within it,
-points to an address outside the allocated address space of the process.
.It Bq Er ENOENT
The jail referred to by a
.Va jid
@@ -564,6 +487,10 @@ parameter has been removed
.It Bq Er EINVAL
A supplied parameter is the wrong size.
.It Bq Er EINVAL
+A supplied parameter is out of range.
+.It Bq Er EINVAL
+A supplied string parameter is not null-terminated.
+.It Bq Er EINVAL
A supplied parameter name does not match any known parameters.
.It Bq Er EMFILE
A jail descriptor could not be created for the
@@ -607,18 +534,10 @@ and
system calls
will fail if:
.Bl -tag -width Er
-.It Bq Er EBADF
+.It Bq Er EINVAL
The
.Fa fd
argument is not a valid jail descriptor.
-.It Bq Er EACCES
-Permission is denied on the jail descriptor
-.Po
-execute permission for
-.Fn jail_attach_fd ,
-or write permission for
-.Fn jail_remove_fd
-.Pc .
.It Bq Er EPERM
The jail descriptor was created by a user other than the super-user.
.It Bq Er EINVAL
@@ -636,6 +555,9 @@ and
call
.Xr chroot 2
internally, so they can fail for all the same reasons.
+In particular, they return the
+.Bq Er EPERM
+error when the process to join a jail has open directories.
Please consult the
.Xr chroot 2
manual page for details.
diff --git a/lib/libsys/kqueue.2 b/lib/libsys/kqueue.2
index e413f7d4fbca..96c9b0222a37 100644
--- a/lib/libsys/kqueue.2
+++ b/lib/libsys/kqueue.2
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd September 4, 2025
+.Dd September 12, 2025
.Dt KQUEUE 2
.Os
.Sh NAME
@@ -614,41 +614,43 @@ The process ID will be stored in
If more than one process has attached since the last call to
.Fn kevent ,
.Va data
-will contain the most recently attached process ID,
-with
-.Dv NOTE_JAIL_ATTACH_MULTI
-set in
-.Va fflags .
+will be zero.
.It Dv NOTE_JAIL_REMOVE
The jail has been removed.
.It Dv NOTE_JAIL_CHILD
A child of the watched jail has been created.
-.It Dv NOTE_TRACK
-Follow child jails created under this jail.
-Register a new kevent to monitor the child jail using the same
-.Va fflags
-as the original event.
-The child jail will signal an event with
-.Dv NOTE_CHILD
-set in
-.Va fflags
-and the parent JID in
+Its jail ID will be stored in
.Va data .
-.Pp
-If registering a new kevent fails
-.Pq usually due to resource limitations ,
-it will signal an event with
-.Dv NOTE_TRACKERR
-set in
-.Va fflags ,
-and the child jail will not signal a
-.Dv NOTE_CHILD
-event.
+If more than one jail has been created since the last call to
+.Fn kevent ,
+.Va data
+will be zero.
.El
.Pp
On return,
.Va fflags
contains the events which triggered the filter.
+It will also contain
+.Dv NOTE_JAIL_MULTI
+if more than one
+.Dv NOTE_JAIL_ATTACH
+or
+.Dv NOTE_JAIL_CHILD
+event has been received since the last call to
+.Fn kevent .
+.It Dv EVFILT_JAILDESC
+Takes a jail descriptor returned by
+.Xr jail_set 2
+or
+.Xr jail_get 2
+as the identifier and the events to watch for in
+.Va fflags ,
+and returns when the jail performs one or more of the requested events.
+The events to monitor and the resulting
+.Va fflags
+are the same as those listed in
+.Dv EVFILT_JAIL ,
+above.
.It Dv EVFILT_TIMER
Establishes an arbitrary timer identified by
.Va ident .
diff --git a/lib/libsys/setcred.2 b/lib/libsys/setcred.2
index 86f61ddfdb30..f5d1f15b631b 100644
--- a/lib/libsys/setcred.2
+++ b/lib/libsys/setcred.2
@@ -6,7 +6,7 @@
.\" This documentation was written by Olivier Certner <olce.freebsd@certner.fr>
.\" at Kumacom SARL under sponsorship from the FreeBSD Foundation.
.\"
-.Dd December 19, 2024
+.Dd August 29, 2025
.Dt SETCRED 2
.Os
.Sh NAME
@@ -119,11 +119,6 @@ It must be less than or equal to
An array of IDs to set the supplementary groups to, if flag
.Dv SETCREDF_SUPP_GROUPS
is specified.
-Note that all groups in this array will be set as supplementary groups only, in
-contrast to
-.Xr setgroups 2
-which treats the first element specially as the new effective group, not adding
-it to supplementary groups.
.It Fa sc_label
A pointer to a valid MAC label structure, e.g., built with the
.Xr mac_from_text 3
diff --git a/lib/libsys/setgroups.2 b/lib/libsys/setgroups.2
index 451f63ba1266..0ec99507cfb0 100644
--- a/lib/libsys/setgroups.2
+++ b/lib/libsys/setgroups.2
@@ -1,5 +1,13 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
.\" Copyright (c) 1983, 1991, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 2025 The FreeBSD Foundation
+.\"
+.\" Portions of this documentation were written by Olivier Certner
+.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD
+.\" Foundation.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -25,12 +33,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd August 1, 2025
+.Dd September 17, 2025
.Dt SETGROUPS 2
.Os
.Sh NAME
.Nm setgroups
-.Nd set group access list
+.Nd set the calling process' supplementary groups
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -41,21 +49,21 @@
.Sh DESCRIPTION
The
.Fn setgroups
-system call
-sets the supplementary group list of the current user process
-according to the array
-.Fa gidset .
+system call sets the calling process' supplementary groups according to the
+.Fa gidset
+array.
The
.Fa ngroups
-argument
-indicates the number of entries in the array and must be no
-more than
+argument indicates the number of entries in the array and must be no more than
.Dv {NGROUPS_MAX} .
+.Pp
The
.Fa ngroups
-argument may be set to 0 to clear the supplementary group list.
+argument may be set to zero to clear all supplementary groups, in which case
+.Fa gidset
+is ignored.
.Pp
-Only the super-user may set a new supplementary group list.
+Only the super-user may install a new supplementary groups set.
.Sh RETURN VALUES
.Rv -std setgroups
.Sh ERRORS
@@ -69,16 +77,16 @@ The caller is not the super-user.
The number specified in the
.Fa ngroups
argument is larger than the
-.Dv {NGROUPS_MAX}+1
+.Dv {NGROUPS_MAX}
limit.
.It Bq Er EFAULT
-The address specified for
+Part of the groups array starting at
.Fa gidset
-is outside the process
-address space.
+is outside the process address space.
.El
.Sh SEE ALSO
.Xr getgroups 2 ,
+.Xr setcred 2 ,
.Xr initgroups 3
.Sh HISTORY
The
@@ -92,4 +100,63 @@ the
.Fn setgroups
system call would set the effective group ID for the process to the first
element of
-.Fa gidset .
+.Fa gidset ,
+and only the other elements as supplementary groups.
+Despite treating the first element as the effective group ID to set, it accepted
+an empty
+.Fa gidset
+.Po
+.Fa ngroups
+being zero
+.Pc
+as a stance requiring to drop all supplementary groups, leaving the effective
+group ID unchanged.
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn setgroups
+system call sets the process' supplementary groups to those contained in the
+.Fa gidset
+array.
+In particular, as evoked in
+.Sx HISTORY ,
+it does not anymore treat the first element of
+.Fa gidset
+separately.
+Formerly, it would set it as the effective group ID while only the others were
+used as supplementary groups.
+.Pp
+Programs solely relying on
+.Fn setgroups
+to change the effective group ID must be modified, e.g., to also call
+.Xr setegid 2
+or to instead use
+.Xr setcred 2 ,
+else they will unwillingly keep their effective group ID.
+.Pp
+Programs using
+.Fn setgroups
+with the effective group ID as the first element of array
+.Fa gidset
+and not duplicating it in the rest of the array, which includes those using
+.Fn initgroups ,
+now insert this group ID in the supplementary groups set.
+This is in general desirable, as explained in the
+.Xr initgroups 3
+manual page, and has the consequence that subsequent process' effective group
+ID's changes do not remove membership of the original effective group ID, since
+these changes do not affect the supplementary groups.
+Applications that expressly do not want that must be modified to stop passing
+the effective group ID as the first element to
+.Fn setgroups .
+.Pp
+To clear all the calling process' supplementary groups, always use the statement
+.Bd -literal -offset indent
+setgroups(0, NULL);
+.Ed
+.Pp
+which works also on older FreeBSD version
+.Po
+see the
+.Sx HISTORY
+section
+.Pc .
diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile
index ab913f834bb3..3b1911d7a5cd 100644
--- a/lib/libufs/Makefile
+++ b/lib/libufs/Makefile
@@ -1,4 +1,6 @@
-PACKAGE= libufs
+PACKAGE= ufs
+LIB_PACKAGE=
+
LIB= ufs
SHLIBDIR?= /lib
SHLIB_MAJOR= 8
diff --git a/lib/libunbound/Makefile b/lib/libunbound/Makefile
index cdc965c20763..e2cd25ea8b34 100644
--- a/lib/libunbound/Makefile
+++ b/lib/libunbound/Makefile
@@ -13,23 +13,20 @@ PACKAGE= unbound
CFLAGS+= -I${UNBOUNDDIR} -I${LDNSDIR} -I${.OBJDIR} -I${.CURDIR}
CFLAGS+= -DOPENSSL_API_COMPAT=0x10100000L
-SRCS= alloc.c as112.c authzone.c autotrust.c cachedb.c config_file.c \
- configlexer.l configparser.y context.c dname.c dns.c dns64.c \
- dnstree.c edns.c fptr_wlist.c infra.c iter_delegpt.c iter_donotq.c \
- iter_fwd.c iter_hints.c iter_priv.c iter_resptype.c iter_scrub.c \
- iter_utils.c iterator.c keyraw.c libunbound.c libworker.c \
- listen_dnsport.c localzone.c locks.c log.c lookup3.c lruhash.c \
- mesh.c mini_event.c modstack.c module.c msgencode.c msgparse.c \
- msgreply.c net_help.c netevent.c outbound_list.c outside_network.c \
- packed_rrset.c parse.c parseutil.c proxy_protocol.c \
- random.c rbtree.c redis.c \
- regional.c respip.c rfc_1982.c rpz.c rrdef.c rrset.c rtt.c sbuffer.c \
- siphash.c slabhash.c \
- str2wire.c tcp_conn_limit.c timehist.c timeval_func.c \
- tube.c ub_event_pluggable.c \
- val_anchor.c val_kcache.c val_kentry.c val_neg.c val_nsec.c \
- val_nsec3.c val_secalgo.c val_sigcrypt.c val_utils.c validator.c \
- view.c winsock_event.c wire2str.c
+SRCS= alloc.c as112.c authzone.c autotrust.c config_file.c configlexer.l \
+ configparser.y context.c dname.c dns.c dns64.c dnstree.c edns.c \
+ fptr_wlist.c infra.c iter_delegpt.c iter_donotq.c iter_fwd.c \
+ iter_hints.c iter_priv.c iter_resptype.c iter_scrub.c iter_utils.c \
+ iterator.c keyraw.c libunbound.c libworker.c listen_dnsport.c \
+ localzone.c locks.c log.c lookup3.c lruhash.c mesh.c mini_event.c \
+ modstack.c module.c msgencode.c msgparse.c msgreply.c net_help.c \
+ netevent.c outbound_list.c outside_network.c packed_rrset.c parse.c \
+ parseutil.c proxy_protocol.c random.c rbtree.c regional.c respip.c \
+ rfc_1982.c rpz.c rrdef.c rrset.c rtt.c sbuffer.c siphash.c \
+ slabhash.c str2wire.c tcp_conn_limit.c timehist.c timeval_func.c \
+ tube.c ub_event_pluggable.c val_anchor.c val_kcache.c val_kentry.c \
+ val_neg.c val_nsec.c val_nsec3.c val_secalgo.c val_sigcrypt.c \
+ val_utils.c validator.c view.c winsock_event.c wire2str.c
WARNS?= 2
NO_WTHREAD_SAFETY= true
diff --git a/lib/libunbound/config.h b/lib/libunbound/config.h
index a986bfc869a3..51105977b20a 100644
--- a/lib/libunbound/config.h
+++ b/lib/libunbound/config.h
@@ -20,7 +20,7 @@
/* #undef COMPAT_SHA512 */
/* Command line arguments used with configure */
-#define CONFCMDLINE "--with-ssl=/usr --with-libexpat=/usr --disable-dnscrypt --disable-dnstap --enable-ecdsa --disable-event-api --enable-gost --with-libevent --disable-subnet --disable-tfo-client --disable-tfo-server --with-pthreads--prefix=/usr --localstatedir=/var/unbound --mandir=/usr/share/man --build=freebsd"
+#define CONFCMDLINE "--prefix= --exec-prefix=/usr --with-conf-file=/var/unbound/unbound.conf --with-run-dir=/var/unbound --with-username=unbound"
/* Pathname to the Unbound configuration file */
#define CONFIGFILE "/var/unbound/unbound.conf"
@@ -49,13 +49,13 @@
internal symbols */
/* #undef EXPORT_ALL_SYMBOLS */
-/* Define to 1 if you have the `accept4' function. */
+/* Define to 1 if you have the 'accept4' function. */
#define HAVE_ACCEPT4 1
-/* Define to 1 if you have the `arc4random' function. */
+/* Define to 1 if you have the 'arc4random' function. */
#define HAVE_ARC4RANDOM 1
-/* Define to 1 if you have the `arc4random_uniform' function. */
+/* Define to 1 if you have the 'arc4random_uniform' function. */
#define HAVE_ARC4RANDOM_UNIFORM 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
@@ -77,13 +77,10 @@
#define HAVE_ATTR_WEAK 1
/* If we have be64toh */
-/* #undef HAVE_BE64TOH */
+#define HAVE_BE64TOH 1
-/* Define to 1 if you have the `BIO_set_callback_ex' function. */
-/* #undef HAVE_BIO_SET_CALLBACK_EX */
-
-/* Define to 1 if you have the `BIO_set_callback_ex' function. */
-/* #undef HAVE_BIO_SET_CALLBACK_EX */
+/* Define to 1 if you have the 'BIO_set_callback_ex' function. */
+#define HAVE_BIO_SET_CALLBACK_EX 1
/* Define to 1 if you have the <bsd/stdlib.h> header file. */
/* #undef HAVE_BSD_STDLIB_H */
@@ -91,241 +88,241 @@
/* Define to 1 if you have the <bsd/string.h> header file. */
/* #undef HAVE_BSD_STRING_H */
-/* Define to 1 if you have the `chown' function. */
+/* Define to 1 if you have the 'chown' function. */
#define HAVE_CHOWN 1
-/* Define to 1 if you have the `chroot' function. */
+/* Define to 1 if you have the 'chroot' function. */
#define HAVE_CHROOT 1
-/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/* Define to 1 if you have the 'CRYPTO_cleanup_all_ex_data' function. */
/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
-/* Define to 1 if you have the `CRYPTO_THREADID_set_callback' function. */
+/* Define to 1 if you have the 'CRYPTO_THREADID_set_callback' function. */
/* #undef HAVE_CRYPTO_THREADID_SET_CALLBACK */
-/* Define to 1 if you have the `ctime_r' function. */
+/* Define to 1 if you have the 'ctime_r' function. */
#define HAVE_CTIME_R 1
-/* Define to 1 if you have the `daemon' function. */
+/* Define to 1 if you have the 'daemon' function. */
#define HAVE_DAEMON 1
-/* Define to 1 if you have the declaration of `arc4random', and to 0 if you
+/* Define to 1 if you have the declaration of 'arc4random', and to 0 if you
don't. */
/* #undef HAVE_DECL_ARC4RANDOM */
-/* Define to 1 if you have the declaration of `arc4random_uniform', and to 0
+/* Define to 1 if you have the declaration of 'arc4random_uniform', and to 0
if you don't. */
/* #undef HAVE_DECL_ARC4RANDOM_UNIFORM */
-/* Define to 1 if you have the declaration of `evsignal_assign', and to 0 if
+/* Define to 1 if you have the declaration of 'evsignal_assign', and to 0 if
you don't. */
/* #undef HAVE_DECL_EVSIGNAL_ASSIGN */
-/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you
+/* Define to 1 if you have the declaration of 'inet_ntop', and to 0 if you
don't. */
#define HAVE_DECL_INET_NTOP 1
-/* Define to 1 if you have the declaration of `inet_pton', and to 0 if you
+/* Define to 1 if you have the declaration of 'inet_pton', and to 0 if you
don't. */
#define HAVE_DECL_INET_PTON 1
-/* Define to 1 if you have the declaration of `nghttp2_session_server_new',
+/* Define to 1 if you have the declaration of 'nghttp2_session_server_new',
and to 0 if you don't. */
/* #undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW */
-/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
+/* Define to 1 if you have the declaration of 'ngtcp2_conn_server_new', and to
+ 0 if you don't. */
+/* #undef HAVE_DECL_NGTCP2_CONN_SERVER_NEW */
+
+/* Define to 1 if you have the declaration of 'ngtcp2_crypto_encrypt_cb', and
+ to 0 if you don't. */
+/* #undef HAVE_DECL_NGTCP2_CRYPTO_ENCRYPT_CB */
+
+/* Define to 1 if you have the declaration of 'NID_ED25519', and to 0 if you
don't. */
#define HAVE_DECL_NID_ED25519 1
-/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you
+/* Define to 1 if you have the declaration of 'NID_ED448', and to 0 if you
don't. */
#define HAVE_DECL_NID_ED448 1
-/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
+/* Define to 1 if you have the declaration of 'NID_secp384r1', and to 0 if you
don't. */
#define HAVE_DECL_NID_SECP384R1 1
-/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0
+/* Define to 1 if you have the declaration of 'NID_X9_62_prime256v1', and to 0
if you don't. */
#define HAVE_DECL_NID_X9_62_PRIME256V1 1
-/* Define to 1 if you have the declaration of `reallocarray', and to 0 if you
+/* Define to 1 if you have the declaration of 'reallocarray', and to 0 if you
don't. */
#define HAVE_DECL_REALLOCARRAY 1
-/* Define to 1 if you have the declaration of `redisConnect', and to 0 if you
+/* Define to 1 if you have the declaration of 'redisConnect', and to 0 if you
don't. */
/* #undef HAVE_DECL_REDISCONNECT */
-/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0
+/* Define to 1 if you have the declaration of 'sk_SSL_COMP_pop_free', and to 0
if you don't. */
#define HAVE_DECL_SK_SSL_COMP_POP_FREE 1
/* Define to 1 if you have the declaration of
- `SSL_COMP_get_compression_methods', and to 0 if you don't. */
+ 'SSL_COMP_get_compression_methods', and to 0 if you don't. */
#define HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS 1
-/* Define to 1 if you have the declaration of `SSL_CTX_set_ecdh_auto', and to
+/* Define to 1 if you have the declaration of 'SSL_CTX_set_ecdh_auto', and to
0 if you don't. */
-/* #undef HAVE_DECL_SSL_CTX_SET_ECDH_AUTO */
+#define HAVE_DECL_SSL_CTX_SET_ECDH_AUTO 1
-/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
+/* Define to 1 if you have the declaration of 'strlcat', and to 0 if you
don't. */
/* #undef HAVE_DECL_STRLCAT */
-/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you
+/* Define to 1 if you have the declaration of 'strlcpy', and to 0 if you
don't. */
/* #undef HAVE_DECL_STRLCPY */
-/* Define to 1 if you have the declaration of `XML_StopParser', and to 0 if
+/* Define to 1 if you have the declaration of 'XML_StopParser', and to 0 if
you don't. */
#define HAVE_DECL_XML_STOPPARSER 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
-/* Define to 1 if you have the `DSA_SIG_set0' function. */
+/* Define to 1 if you have the 'DSA_SIG_set0' function. */
#define HAVE_DSA_SIG_SET0 1
/* Define to 1 if you have the <endian.h> header file. */
-/* #undef HAVE_ENDIAN_H */
+#define HAVE_ENDIAN_H 1
-/* Define to 1 if you have the `endprotoent' function. */
+/* Define to 1 if you have the 'endprotoent' function. */
#define HAVE_ENDPROTOENT 1
-/* Define to 1 if you have the `endpwent' function. */
+/* Define to 1 if you have the 'endpwent' function. */
#define HAVE_ENDPWENT 1
-/* Define to 1 if you have the `endservent' function. */
+/* Define to 1 if you have the 'endservent' function. */
#define HAVE_ENDSERVENT 1
-/* Define to 1 if you have the `ENGINE_cleanup' function. */
+/* Define to 1 if you have the 'ENGINE_cleanup' function. */
/* #undef HAVE_ENGINE_CLEANUP */
-/* Define to 1 if you have the `ERR_free_strings' function. */
+/* Define to 1 if you have the 'ERR_free_strings' function. */
/* #undef HAVE_ERR_FREE_STRINGS */
-/* Define to 1 if you have the `ERR_load_crypto_strings' function. */
+/* Define to 1 if you have the 'ERR_load_crypto_strings' function. */
/* #undef HAVE_ERR_LOAD_CRYPTO_STRINGS */
-/* Define to 1 if you have the `event_assign' function. */
+/* Define to 1 if you have the 'event_assign' function. */
/* #undef HAVE_EVENT_ASSIGN */
-/* Define to 1 if you have the `event_base_free' function. */
+/* Define to 1 if you have the 'event_base_free' function. */
/* #undef HAVE_EVENT_BASE_FREE */
-/* Define to 1 if you have the `event_base_get_method' function. */
+/* Define to 1 if you have the 'event_base_get_method' function. */
/* #undef HAVE_EVENT_BASE_GET_METHOD */
-/* Define to 1 if you have the `event_base_new' function. */
+/* Define to 1 if you have the 'event_base_new' function. */
/* #undef HAVE_EVENT_BASE_NEW */
-/* Define to 1 if you have the `event_base_once' function. */
+/* Define to 1 if you have the 'event_base_once' function. */
/* #undef HAVE_EVENT_BASE_ONCE */
/* Define to 1 if you have the <event.h> header file. */
/* #undef HAVE_EVENT_H */
-/* Define to 1 if you have the `EVP_aes_256_cbc' function. */
+/* Define to 1 if you have the 'EVP_aes_256_cbc' function. */
#define HAVE_EVP_AES_256_CBC 1
-/* Define to 1 if you have the `EVP_cleanup' function. */
+/* Define to 1 if you have the 'EVP_cleanup' function. */
/* #undef HAVE_EVP_CLEANUP */
-/* Define to 1 if you have the `EVP_default_properties_is_fips_enabled'
+/* Define to 1 if you have the 'EVP_default_properties_is_fips_enabled'
function. */
-/* #undef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED */
-
+#define HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED 1
-/* Define to 1 if you have the `EVP_default_properties_is_fips_enabled'
- function. */
-/* #undef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED */
-
-/* Define to 1 if you have the `EVP_DigestVerify' function. */
+/* Define to 1 if you have the 'EVP_DigestVerify' function. */
#define HAVE_EVP_DIGESTVERIFY 1
-/* Define to 1 if you have the `EVP_dss1' function. */
+/* Define to 1 if you have the 'EVP_dss1' function. */
/* #undef HAVE_EVP_DSS1 */
-/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
+/* Define to 1 if you have the 'EVP_EncryptInit_ex' function. */
#define HAVE_EVP_ENCRYPTINIT_EX 1
-/* Define to 1 if you have the `EVP_MAC_CTX_set_params' function. */
-/* #undef HAVE_EVP_MAC_CTX_SET_PARAMS */
+/* Define to 1 if you have the 'EVP_MAC_CTX_set_params' function. */
+#define HAVE_EVP_MAC_CTX_SET_PARAMS 1
-/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
+/* Define to 1 if you have the 'EVP_MD_CTX_new' function. */
#define HAVE_EVP_MD_CTX_NEW 1
-/* Define to 1 if you have the `EVP_sha1' function. */
+/* Define to 1 if you have the 'EVP_sha1' function. */
#define HAVE_EVP_SHA1 1
-/* Define to 1 if you have the `EVP_sha256' function. */
+/* Define to 1 if you have the 'EVP_sha256' function. */
#define HAVE_EVP_SHA256 1
-/* Define to 1 if you have the `EVP_sha512' function. */
+/* Define to 1 if you have the 'EVP_sha512' function. */
#define HAVE_EVP_SHA512 1
-/* Define to 1 if you have the `ev_default_loop' function. */
+/* Define to 1 if you have the 'ev_default_loop' function. */
/* #undef HAVE_EV_DEFAULT_LOOP */
-/* Define to 1 if you have the `ev_loop' function. */
+/* Define to 1 if you have the 'ev_loop' function. */
/* #undef HAVE_EV_LOOP */
/* Define to 1 if you have the <expat.h> header file. */
#define HAVE_EXPAT_H 1
-/* Define to 1 if you have the `explicit_bzero' function. */
+/* Define to 1 if you have the 'explicit_bzero' function. */
#define HAVE_EXPLICIT_BZERO 1
-/* Define to 1 if you have the `fcntl' function. */
+/* Define to 1 if you have the 'fcntl' function. */
#define HAVE_FCNTL 1
-/* Define to 1 if you have the `FIPS_mode' function. */
-#define HAVE_FIPS_MODE 1
+/* Define to 1 if you have the 'FIPS_mode' function. */
+/* #undef HAVE_FIPS_MODE */
-/* Define to 1 if you have the `fork' function. */
+/* Define to 1 if you have the 'fork' function. */
#define HAVE_FORK 1
-/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+/* Define to 1 if fseeko (and ftello) are declared in stdio.h. */
#define HAVE_FSEEKO 1
-/* Define to 1 if you have the `fsync' function. */
+/* Define to 1 if you have the 'fsync' function. */
#define HAVE_FSYNC 1
/* Whether getaddrinfo is available */
#define HAVE_GETADDRINFO 1
-/* Define to 1 if you have the `getauxval' function. */
+/* Define to 1 if you have the 'getauxval' function. */
/* #undef HAVE_GETAUXVAL */
-/* Define to 1 if you have the `getentropy' function. */
+/* Define to 1 if you have the 'getentropy' function. */
/* #undef HAVE_GETENTROPY */
-/* Define to 1 if you have the `getifaddrs' function. */
+/* Define to 1 if you have the 'getifaddrs' function. */
#define HAVE_GETIFADDRS 1
/* Define to 1 if you have the <getopt.h> header file. */
#define HAVE_GETOPT_H 1
-/* Define to 1 if you have the `getpwnam' function. */
+/* Define to 1 if you have the 'getpwnam' function. */
#define HAVE_GETPWNAM 1
-/* Define to 1 if you have the `getrlimit' function. */
+/* Define to 1 if you have the 'getrlimit' function. */
#define HAVE_GETRLIMIT 1
-/* Define to 1 if you have the `gettid' function. */
-/* #undef HAVE_GETTID */
-
-/* Define to 1 if you have the `gettid' function. */
+/* Define to 1 if you have the 'gettid' function. */
/* #undef HAVE_GETTID */
-/* Define to 1 if you have the `glob' function. */
+/* Define to 1 if you have the 'glob' function. */
#define HAVE_GLOB 1
/* Define to 1 if you have the <glob.h> header file. */
#define HAVE_GLOB_H 1
-/* Define to 1 if you have the `gmtime_r' function. */
+/* Define to 1 if you have the 'gmtime_r' function. */
#define HAVE_GMTIME_R 1
/* Define to 1 if you have the <grp.h> header file. */
@@ -334,31 +331,28 @@
/* Define to 1 if you have the <hiredis/hiredis.h> header file. */
/* #undef HAVE_HIREDIS_HIREDIS_H */
-/* Define to 1 if you have the `HMAC_Init_ex' function. */
+/* Define to 1 if you have the 'HMAC_Init_ex' function. */
#define HAVE_HMAC_INIT_EX 1
/* If we have htobe64 */
-/* #undef HAVE_HTOBE64 */
+#define HAVE_HTOBE64 1
/* Define to 1 if you have the <ifaddrs.h> header file. */
#define HAVE_IFADDRS_H 1
-/* Define to 1 if you have the `if_nametoindex' function. */
+/* Define to 1 if you have the 'if_nametoindex' function. */
#define HAVE_IF_NAMETOINDEX 1
-/* Define to 1 if you have the `if_nametoindex' function. */
-#define HAVE_IF_NAMETOINDEX 1
-
-/* Define to 1 if you have the `inet_aton' function. */
+/* Define to 1 if you have the 'inet_aton' function. */
#define HAVE_INET_ATON 1
-/* Define to 1 if you have the `inet_ntop' function. */
+/* Define to 1 if you have the 'inet_ntop' function. */
#define HAVE_INET_NTOP 1
-/* Define to 1 if you have the `inet_pton' function. */
+/* Define to 1 if you have the 'inet_pton' function. */
#define HAVE_INET_PTON 1
-/* Define to 1 if you have the `initgroups' function. */
+/* Define to 1 if you have the 'initgroups' function. */
#define HAVE_INITGROUPS 1
/* Define to 1 if you have the <inttypes.h> header file. */
@@ -370,10 +364,10 @@
/* Define to 1 if you have the <iphlpapi.h> header file. */
/* #undef HAVE_IPHLPAPI_H */
-/* Define to 1 if you have the `isblank' function. */
+/* Define to 1 if you have the 'isblank' function. */
#define HAVE_ISBLANK 1
-/* Define to 1 if you have the `kill' function. */
+/* Define to 1 if you have the 'kill' function. */
#define HAVE_KILL 1
/* Use portable libbsd functions */
@@ -385,7 +379,13 @@
/* Define if we have LibreSSL */
/* #undef HAVE_LIBRESSL */
-/* Define to 1 if you have the `localtime_r' function. */
+/* If we have atomic_store */
+#define HAVE_LINK_ATOMIC_STORE 1
+
+/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
+/* #undef HAVE_LINUX_NET_TSTAMP_H */
+
+/* Define to 1 if you have the 'localtime_r' function. */
#define HAVE_LOCALTIME_R 1
/* Define to 1 if you have the <login_cap.h> header file. */
@@ -394,7 +394,7 @@
/* If have GNU libc compatible malloc */
#define HAVE_MALLOC 1
-/* Define to 1 if you have the `memmove' function. */
+/* Define to 1 if you have the 'memmove' function. */
#define HAVE_MEMMOVE 1
/* Define to 1 if you have the <minix/config.h> header file. */
@@ -424,29 +424,91 @@
/* Define to 1 if you have the <net/if.h> header file. */
#define HAVE_NET_IF_H 1
+/* Define to 1 if you have the <net/pfvar.h> header file. */
+/* #undef HAVE_NET_PFVAR_H */
+
/* Define this to use nghttp2 client. */
/* #undef HAVE_NGHTTP2 */
/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
/* #undef HAVE_NGHTTP2_NGHTTP2_H */
+/* Define this to use ngtcp2. */
+/* #undef HAVE_NGTCP2 */
+
+/* Define to 1 if you have the 'ngtcp2_ccerr_default' function. */
+/* #undef HAVE_NGTCP2_CCERR_DEFAULT */
+
+/* Define to 1 if you have the 'ngtcp2_conn_encode_0rtt_transport_params'
+ function. */
+/* #undef HAVE_NGTCP2_CONN_ENCODE_0RTT_TRANSPORT_PARAMS */
+
+/* Define to 1 if you have the 'ngtcp2_conn_get_max_local_streams_uni'
+ function. */
+/* #undef HAVE_NGTCP2_CONN_GET_MAX_LOCAL_STREAMS_UNI */
+
+/* Define to 1 if you have the 'ngtcp2_conn_get_num_scid' function. */
+/* #undef HAVE_NGTCP2_CONN_GET_NUM_SCID */
+
+/* Define to 1 if you have the 'ngtcp2_conn_in_closing_period' function. */
+/* #undef HAVE_NGTCP2_CONN_IN_CLOSING_PERIOD */
+
+/* Define to 1 if you have the 'ngtcp2_conn_in_draining_period' function. */
+/* #undef HAVE_NGTCP2_CONN_IN_DRAINING_PERIOD */
+
+/* Define if ngtcp2_conn_shutdown_stream has 4 arguments. */
+/* #undef HAVE_NGTCP2_CONN_SHUTDOWN_STREAM4 */
+
+/* Define to 1 if you have the 'ngtcp2_conn_tls_early_data_rejected' function.
+ */
+/* #undef HAVE_NGTCP2_CONN_TLS_EARLY_DATA_REJECTED */
+
+/* Define to 1 if you have the 'ngtcp2_crypto_encrypt_cb' function. */
+/* #undef HAVE_NGTCP2_CRYPTO_ENCRYPT_CB */
+
+/* Define to 1 if you have the
+ 'ngtcp2_crypto_quictls_configure_client_context' function. */
+/* #undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_CLIENT_CONTEXT */
+
+/* Define to 1 if you have the
+ 'ngtcp2_crypto_quictls_configure_server_context' function. */
+/* #undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT */
+
+/* Define to 1 if you have the
+ 'ngtcp2_crypto_quictls_from_ossl_encryption_level' function. */
+/* #undef HAVE_NGTCP2_CRYPTO_QUICTLS_FROM_OSSL_ENCRYPTION_LEVEL */
+
+/* Define to 1 if the system has the type 'ngtcp2_encryption_level'. */
+/* #undef HAVE_NGTCP2_ENCRYPTION_LEVEL */
+
+/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_openssl.h> header file.
+ */
+/* #undef HAVE_NGTCP2_NGTCP2_CRYPTO_OPENSSL_H */
+
+/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_quictls.h> header file.
+ */
+/* #undef HAVE_NGTCP2_NGTCP2_CRYPTO_QUICTLS_H */
+
+/* Define to 1 if you have the <ngtcp2/ngtcp2.h> header file. */
+/* #undef HAVE_NGTCP2_NGTCP2_H */
+
/* Use libnss for crypto */
/* #undef HAVE_NSS */
-/* Define to 1 if you have the `OpenSSL_add_all_digests' function. */
+/* Define to 1 if you have the 'OpenSSL_add_all_digests' function. */
/* #undef HAVE_OPENSSL_ADD_ALL_DIGESTS */
/* Define to 1 if you have the <openssl/bn.h> header file. */
#define HAVE_OPENSSL_BN_H 1
-/* Define to 1 if you have the `OPENSSL_config' function. */
+/* Define to 1 if you have the 'OPENSSL_config' function. */
#define HAVE_OPENSSL_CONFIG 1
/* Define to 1 if you have the <openssl/conf.h> header file. */
#define HAVE_OPENSSL_CONF_H 1
/* Define to 1 if you have the <openssl/core_names.h> header file. */
-/* #undef HAVE_OPENSSL_CORE_NAMES_H */
+#define HAVE_OPENSSL_CORE_NAMES_H 1
/* Define to 1 if you have the <openssl/dh.h> header file. */
#define HAVE_OPENSSL_DH_H 1
@@ -460,14 +522,14 @@
/* Define to 1 if you have the <openssl/err.h> header file. */
#define HAVE_OPENSSL_ERR_H 1
-/* Define to 1 if you have the `OPENSSL_init_crypto' function. */
+/* Define to 1 if you have the 'OPENSSL_init_crypto' function. */
#define HAVE_OPENSSL_INIT_CRYPTO 1
-/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
+/* Define to 1 if you have the 'OPENSSL_init_ssl' function. */
#define HAVE_OPENSSL_INIT_SSL 1
/* Define to 1 if you have the <openssl/param_build.h> header file. */
-/* #undef HAVE_OPENSSL_PARAM_BUILD_H */
+#define HAVE_OPENSSL_PARAM_BUILD_H 1
/* Define to 1 if you have the <openssl/rand.h> header file. */
#define HAVE_OPENSSL_RAND_H 1
@@ -478,10 +540,10 @@
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#define HAVE_OPENSSL_SSL_H 1
-/* Define to 1 if you have the `OSSL_PARAM_BLD_new' function. */
-/* #undef HAVE_OSSL_PARAM_BLD_NEW */
+/* Define to 1 if you have the 'OSSL_PARAM_BLD_new' function. */
+#define HAVE_OSSL_PARAM_BLD_NEW 1
-/* Define to 1 if you have the `poll' function. */
+/* Define to 1 if you have the 'poll' function. */
#define HAVE_POLL 1
/* Define to 1 if you have the <poll.h> header file. */
@@ -493,10 +555,10 @@
/* Have PTHREAD_PRIO_INHERIT. */
#define HAVE_PTHREAD_PRIO_INHERIT 1
-/* Define to 1 if the system has the type `pthread_rwlock_t'. */
+/* Define to 1 if the system has the type 'pthread_rwlock_t'. */
#define HAVE_PTHREAD_RWLOCK_T 1
-/* Define to 1 if the system has the type `pthread_spinlock_t'. */
+/* Define to 1 if the system has the type 'pthread_spinlock_t'. */
#define HAVE_PTHREAD_SPINLOCK_T 1
/* Define to 1 if you have the <pwd.h> header file. */
@@ -505,100 +567,109 @@
/* Define if you have Python libraries and header files. */
/* #undef HAVE_PYTHON */
-/* Define to 1 if you have the `random' function. */
+/* Define to 1 if you have the 'random' function. */
#define HAVE_RANDOM 1
-/* Define to 1 if you have the `RAND_cleanup' function. */
+/* Define to 1 if you have the 'RAND_cleanup' function. */
/* #undef HAVE_RAND_CLEANUP */
/* If we have reallocarray(3) */
#define HAVE_REALLOCARRAY 1
-/* Define to 1 if you have the `recvmsg' function. */
+/* Define to 1 if you have the 'recvmsg' function. */
#define HAVE_RECVMSG 1
-/* Define to 1 if you have the `sendmsg' function. */
+/* Define to 1 if you have the 'sendmsg' function. */
#define HAVE_SENDMSG 1
-/* Define to 1 if you have the `setregid' function. */
+/* Define to 1 if you have the 'setregid' function. */
/* #undef HAVE_SETREGID */
-/* Define to 1 if you have the `setresgid' function. */
+/* Define to 1 if you have the 'setresgid' function. */
#define HAVE_SETRESGID 1
-/* Define to 1 if you have the `setresuid' function. */
+/* Define to 1 if you have the 'setresuid' function. */
#define HAVE_SETRESUID 1
-/* Define to 1 if you have the `setreuid' function. */
+/* Define to 1 if you have the 'setreuid' function. */
/* #undef HAVE_SETREUID */
-/* Define to 1 if you have the `setrlimit' function. */
+/* Define to 1 if you have the 'setrlimit' function. */
#define HAVE_SETRLIMIT 1
-/* Define to 1 if you have the `setsid' function. */
+/* Define to 1 if you have the 'setsid' function. */
#define HAVE_SETSID 1
-/* Define to 1 if you have the `setusercontext' function. */
+/* Define to 1 if you have the 'setusercontext' function. */
#define HAVE_SETUSERCONTEXT 1
-/* Define to 1 if you have the `SHA512_Update' function. */
+/* Define to 1 if you have the 'SHA512_Update' function. */
/* #undef HAVE_SHA512_UPDATE */
-/* Define to 1 if you have the `shmget' function. */
+/* Define to 1 if you have the 'shmget' function. */
#define HAVE_SHMGET 1
-/* Define to 1 if you have the `sigprocmask' function. */
+/* Define to 1 if you have the 'sigprocmask' function. */
#define HAVE_SIGPROCMASK 1
-/* Define to 1 if you have the `sleep' function. */
+/* Define to 1 if you have the 'sleep' function. */
#define HAVE_SLEEP 1
-/* Define to 1 if you have the `snprintf' function. */
+/* Define to 1 if you have the 'snprintf' function. */
#define HAVE_SNPRINTF 1
-/* Define to 1 if you have the `socketpair' function. */
+/* Define to 1 if you have the 'socketpair' function. */
#define HAVE_SOCKETPAIR 1
/* Using Solaris threads */
/* #undef HAVE_SOLARIS_THREADS */
-/* Define to 1 if you have the `srandom' function. */
+/* Define to 1 if you have the 'srandom' function. */
#define HAVE_SRANDOM 1
/* Define if you have the SSL libraries installed. */
#define HAVE_SSL /**/
-/* Define to 1 if you have the `SSL_CTX_set_alpn_protos' function. */
+/* Define to 1 if you have the 'SSL_CTX_set_alpn_protos' function. */
#define HAVE_SSL_CTX_SET_ALPN_PROTOS 1
-/* Define to 1 if you have the `SSL_CTX_set_alpn_select_cb' function. */
+/* Define to 1 if you have the 'SSL_CTX_set_alpn_select_cb' function. */
#define HAVE_SSL_CTX_SET_ALPN_SELECT_CB 1
-/* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function. */
+/* Define to 1 if you have the 'SSL_CTX_set_ciphersuites' function. */
#define HAVE_SSL_CTX_SET_CIPHERSUITES 1
-/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */
+/* Define to 1 if you have the 'SSL_CTX_set_security_level' function. */
#define HAVE_SSL_CTX_SET_SECURITY_LEVEL 1
-/* Define to 1 if you have the `SSL_CTX_set_tlsext_ticket_key_evp_cb'
+/* Define to 1 if you have the 'SSL_CTX_set_tlsext_ticket_key_evp_cb'
function. */
-/* #undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB */
+#define HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 1
+
+/* Define to 1 if you have the 'SSL_CTX_set_tmp_ecdh' function. */
+/* #undef HAVE_SSL_CTX_SET_TMP_ECDH */
-/* Define to 1 if you have the `SSL_get0_alpn_selected' function. */
+/* Define to 1 if you have the 'SSL_get0_alpn_selected' function. */
#define HAVE_SSL_GET0_ALPN_SELECTED 1
-/* Define to 1 if you have the `SSL_get0_peername' function. */
+/* Define to 1 if you have the 'SSL_get0_peername' function. */
#define HAVE_SSL_GET0_PEERNAME 1
-/* Define to 1 if you have the `SSL_get1_peer_certificate' function. */
-/* #undef HAVE_SSL_GET1_PEER_CERTIFICATE */
+/* Define to 1 if you have the 'SSL_get1_peer_certificate' function. */
+#define HAVE_SSL_GET1_PEER_CERTIFICATE 1
-/* Define to 1 if you have the `SSL_set1_host' function. */
+/* Define to 1 if you have the 'SSL_is_quic' function. */
+/* #undef HAVE_SSL_IS_QUIC */
+
+/* Define to 1 if you have the 'SSL_set1_host' function. */
#define HAVE_SSL_SET1_HOST 1
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
+/* Define to 1 if you have the <stdatomic.h> header file. */
+#define HAVE_STDATOMIC_H 1
+
/* Define to 1 if you have the <stdbool.h> header file. */
#define HAVE_STDBOOL_H 1
@@ -611,7 +682,7 @@
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
-/* Define to 1 if you have the `strftime' function. */
+/* Define to 1 if you have the 'strftime' function. */
#define HAVE_STRFTIME 1
/* Define to 1 if you have the <strings.h> header file. */
@@ -620,22 +691,39 @@
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
-/* Define to 1 if you have the `strlcat' function. */
+/* Define to 1 if you have the 'strlcat' function. */
#define HAVE_STRLCAT 1
-/* Define to 1 if you have the `strlcpy' function. */
+/* Define to 1 if you have the 'strlcpy' function. */
#define HAVE_STRLCPY 1
-/* Define to 1 if you have the `strptime' function. */
+/* Define to 1 if you have the 'strptime' function. */
#define HAVE_STRPTIME 1
-/* Define to 1 if you have the `strsep' function. */
+/* Define to 1 if you have the 'strsep' function. */
#define HAVE_STRSEP 1
-/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
+/* Define to 1 if 'ipi_spec_dst' is a member of 'struct in_pktinfo'. */
/* #undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST */
-/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */
+/* Define to 1 if 'tokenlen' is a member of 'struct ngtcp2_pkt_hd'. */
+/* #undef HAVE_STRUCT_NGTCP2_PKT_HD_TOKENLEN */
+
+/* Define to 1 if 'max_tx_udp_payload_size' is a member of 'struct
+ ngtcp2_settings'. */
+/* #undef HAVE_STRUCT_NGTCP2_SETTINGS_MAX_TX_UDP_PAYLOAD_SIZE */
+
+/* Define to 1 if 'tokenlen' is a member of 'struct ngtcp2_settings'. */
+/* #undef HAVE_STRUCT_NGTCP2_SETTINGS_TOKENLEN */
+
+/* Define to 1 if 'original_dcid_present' is a member of 'struct
+ ngtcp2_transport_params'. */
+/* #undef HAVE_STRUCT_NGTCP2_TRANSPORT_PARAMS_ORIGINAL_DCID_PRESENT */
+
+/* Define to 1 if the system has the type 'struct ngtcp2_version_cid'. */
+/* #undef HAVE_STRUCT_NGTCP2_VERSION_CID */
+
+/* Define to 1 if 'sun_len' is a member of 'struct sockaddr_un'. */
#define HAVE_STRUCT_SOCKADDR_UN_SUN_LEN 1
/* Define if you have Swig libraries and header files. */
@@ -695,16 +783,16 @@
/* Define to 1 if you have the <time.h> header file. */
#define HAVE_TIME_H 1
-/* Define to 1 if you have the `tzset' function. */
+/* Define to 1 if you have the 'tzset' function. */
#define HAVE_TZSET 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
-/* Define to 1 if you have the `usleep' function. */
+/* Define to 1 if you have the 'usleep' function. */
#define HAVE_USLEEP 1
-/* Define to 1 if you have the `vfork' function. */
+/* Define to 1 if you have the 'vfork' function. */
#define HAVE_VFORK 1
/* Define to 1 if you have the <vfork.h> header file. */
@@ -722,22 +810,22 @@
/* Define to 1 if you have the <winsock2.h> header file. */
/* #undef HAVE_WINSOCK2_H */
-/* Define to 1 if `fork' works. */
+/* Define to 1 if 'fork' works. */
#define HAVE_WORKING_FORK 1
-/* Define to 1 if `vfork' works. */
+/* Define to 1 if 'vfork' works. */
#define HAVE_WORKING_VFORK 1
-/* Define to 1 if you have the `writev' function. */
+/* Define to 1 if you have the 'writev' function. */
#define HAVE_WRITEV 1
/* Define to 1 if you have the <ws2tcpip.h> header file. */
/* #undef HAVE_WS2TCPIP_H */
-/* Define to 1 if you have the `X509_VERIFY_PARAM_set1_host' function. */
+/* Define to 1 if you have the 'X509_VERIFY_PARAM_set1_host' function. */
#define HAVE_X509_VERIFY_PARAM_SET1_HOST 1
-/* Define to 1 if you have the `_beginthreadex' function. */
+/* Define to 1 if you have the '_beginthreadex' function. */
/* #undef HAVE__BEGINTHREADEX */
/* If HMAC_Init_ex() returns void */
@@ -796,7 +884,7 @@
#define PACKAGE_NAME "unbound"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "unbound 1.23.0"
+#define PACKAGE_STRING "unbound 1.23.1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unbound"
@@ -805,7 +893,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.23.0"
+#define PACKAGE_VERSION "1.23.1"
/* default pidfile location */
#define PIDFILE "/var/unbound/unbound.pid"
@@ -828,7 +916,7 @@
#define ROOT_CERT_FILE "/var/unbound/icannbundle.pem"
/* version number for resource files */
-#define RSRC_PACKAGE_VERSION 1,23,0,0
+#define RSRC_PACKAGE_VERSION 1,23,1,0
/* Directory to chdir to */
#define RUN_DIR "/var/unbound"
@@ -836,32 +924,17 @@
/* Shared data */
#define SHARE_DIR "/var/unbound"
-#ifdef __LP64__
-/* The size of `size_t', as computed by sizeof. */
-#define SIZEOF_SIZE_T 8
-/* The size of `size_t'. */
-/* The size of `pthread_t', as computed by sizeof. */
+/* The size of 'pthread_t', as computed by sizeof. */
#define SIZEOF_PTHREAD_T 8
-#else
-#define SIZEOF_SIZE_T 4
-/* The size of `size_t'. */
-/* The size of `pthread_t', as computed by sizeof. */
-#define SIZEOF_PTHREAD_T 4
-#endif
-/* The size of `time_t', as computed by sizeof. */
-#ifdef __i386__
-#define SIZEOF_TIME_T 4
-#else
+/* The size of 'size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* The size of 'time_t', as computed by sizeof. */
#define SIZEOF_TIME_T 8
-#endif
-/* The size of `unsigned long', as computed by sizeof. */
-#ifdef __LP64__
+/* The size of 'unsigned long', as computed by sizeof. */
#define SIZEOF_UNSIGNED_LONG 8
-#else
-#define SIZEOF_UNSIGNED_LONG 4
-#endif
/* define if (v)snprintf does not return length needed, (but length used) */
/* #undef SNPRINTF_RET_BROKEN */
@@ -869,7 +942,7 @@
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
/* #undef SODIUM_MISUSE_HANDLER */
-/* Define to 1 if all of the C90 standard headers exist (not just the ones
+/* Define to 1 if all of the C89 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#define STDC_HEADERS 1
@@ -911,7 +984,7 @@
/* #undef USE_DNSTAP */
/* Define this to enable DSA support. */
-#define USE_DSA 1
+/* #undef USE_DSA */
/* Define this to enable ECDSA support. */
#define USE_ECDSA 1
@@ -935,7 +1008,7 @@
/* #undef USE_IPSET */
/* Define if you enable libevent */
-#define USE_LIBEVENT 1
+/* #undef USE_LIBEVENT */
/* Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a
default outgoing port range. This is only for the libunbound on Linux and
@@ -963,7 +1036,7 @@
/* Define this to enable SHA256 and SHA512 support. */
#define USE_SHA2 1
-/* Enable extensions on AIX 3, Interix. */
+/* Enable extensions on AIX, Interix, z/OS. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
@@ -1024,11 +1097,15 @@
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
# define __STDC_WANT_IEC_60559_DFP_EXT__ 1
#endif
+/* Enable extensions specified by C23 Annex F. */
+#ifndef __STDC_WANT_IEC_60559_EXT__
+# define __STDC_WANT_IEC_60559_EXT__ 1
+#endif
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1
#endif
-/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
+/* Enable extensions specified by C23 Annex H and ISO/IEC TS 18661-3:2015. */
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
#endif
@@ -1069,30 +1146,36 @@
/* Define if you want PyUnbound. */
/* #undef WITH_PYUNBOUND */
-/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
- `char[]'. */
+/* Define to 1 if 'lex' declares 'yytext' as a 'char *' by default, not a
+ 'char[]'. */
#define YYTEXT_POINTER 1
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+/* Define to 1 if necessary to make fseeko visible. */
/* #undef _LARGEFILE_SOURCE */
-/* Define for large files, on AIX-style hosts. */
+/* Define to 1 on platforms where this makes off_t a 64-bit type. */
/* #undef _LARGE_FILES */
/* Enable for compile on Minix */
#define _NETBSD_SOURCE 1
+/* Number of bits in time_t, on hosts where this is settable. */
+/* #undef _TIME_BITS */
+
+/* Define to 1 on platforms where this makes time_t a 64-bit type. */
+/* #undef __MINGW_USE_VC2005_COMPAT */
+
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
compiled for windows. */
/* #undef __USE_MINGW_ANSI_STDIO */
-/* Define to empty if `const' does not conform to ANSI C. */
+/* Define to empty if 'const' does not conform to ANSI C. */
/* #undef const */
-/* Define to `int' if <sys/types.h> doesn't define. */
+/* Define as 'int' if <sys/types.h> doesn't define. */
/* #undef gid_t */
/* in_addr_t */
@@ -1101,28 +1184,28 @@
/* in_port_t */
/* #undef in_port_t */
-/* Define to `__inline__' or `__inline' if that's what the C compiler
+/* Define to '__inline__' or '__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
-/* Define to `short' if <sys/types.h> does not define. */
+/* Define to 'short' if <sys/types.h> does not define. */
/* #undef int16_t */
-/* Define to `int' if <sys/types.h> does not define. */
+/* Define to 'int' if <sys/types.h> does not define. */
/* #undef int32_t */
-/* Define to `long long' if <sys/types.h> does not define. */
+/* Define to 'long long' if <sys/types.h> does not define. */
/* #undef int64_t */
-/* Define to `signed char' if <sys/types.h> does not define. */
+/* Define to 'signed char' if <sys/types.h> does not define. */
/* #undef int8_t */
/* Define if replacement function should be used. */
/* #undef malloc */
-/* Define to `long int' if <sys/types.h> does not define. */
+/* Define to 'long int' if <sys/types.h> does not define. */
/* #undef off_t */
/* Define as a signed integer type capable of holding a process identifier. */
@@ -1131,71 +1214,71 @@
/* Define to 'int' if not defined */
/* #undef rlim_t */
-/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* Define as 'unsigned int' if <stddef.h> doesn't define. */
/* #undef size_t */
/* Define to 'int' if not defined */
/* #undef socklen_t */
-/* Define to `int' if <sys/types.h> does not define. */
+/* Define to 'int' if <sys/types.h> does not define. */
/* #undef ssize_t */
/* Define to 'unsigned char if not defined */
/* #undef u_char */
-/* Define to `int' if <sys/types.h> doesn't define. */
+/* Define as 'int' if <sys/types.h> doesn't define. */
/* #undef uid_t */
-/* Define to `unsigned short' if <sys/types.h> does not define. */
+/* Define to 'unsigned short' if <sys/types.h> does not define. */
/* #undef uint16_t */
-/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* Define to 'unsigned int' if <sys/types.h> does not define. */
/* #undef uint32_t */
-/* Define to `unsigned long long' if <sys/types.h> does not define. */
+/* Define to 'unsigned long long' if <sys/types.h> does not define. */
/* #undef uint64_t */
-/* Define to `unsigned char' if <sys/types.h> does not define. */
+/* Define to 'unsigned char' if <sys/types.h> does not define. */
/* #undef uint8_t */
-/* Define as `fork' if `vfork' does not work. */
+/* Define as 'fork' if 'vfork' does not work. */
/* #undef vfork */
#if defined(OMITTED__D_GNU_SOURCE) && !defined(_GNU_SOURCE)
#define _GNU_SOURCE 1
-#endif
+#endif
#if defined(OMITTED__D_BSD_SOURCE) && !defined(_BSD_SOURCE)
#define _BSD_SOURCE 1
-#endif
+#endif
#if defined(OMITTED__D_DEFAULT_SOURCE) && !defined(_DEFAULT_SOURCE)
#define _DEFAULT_SOURCE 1
-#endif
+#endif
#if defined(OMITTED__D__EXTENSIONS__) && !defined(__EXTENSIONS__)
#define __EXTENSIONS__ 1
-#endif
+#endif
#if defined(OMITTED__D_POSIX_C_SOURCE_200112) && !defined(_POSIX_C_SOURCE)
#define _POSIX_C_SOURCE 200112
-#endif
+#endif
#if defined(OMITTED__D_XOPEN_SOURCE_600) && !defined(_XOPEN_SOURCE)
#define _XOPEN_SOURCE 600
-#endif
+#endif
#if defined(OMITTED__D_XOPEN_SOURCE_EXTENDED_1) && !defined(_XOPEN_SOURCE_EXTENDED)
#define _XOPEN_SOURCE_EXTENDED 1
-#endif
+#endif
#if defined(OMITTED__D_ALL_SOURCE) && !defined(_ALL_SOURCE)
#define _ALL_SOURCE 1
-#endif
+#endif
#if defined(OMITTED__D_LARGEFILE_SOURCE_1) && !defined(_LARGEFILE_SOURCE)
#define _LARGEFILE_SOURCE 1
-#endif
+#endif
@@ -1279,7 +1362,7 @@
#endif
-
+
#ifdef HAVE_ATTR_FORMAT
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
__attribute__ ((format (archetype, string_index, first_to_check)))
@@ -1389,7 +1472,7 @@ void* reallocarray(void *ptr, size_t nmemb, size_t size);
#ifdef HAVE_WINSOCK2_H
#define FD_SET_T (u_int)
#else
-#define FD_SET_T
+#define FD_SET_T
#endif
@@ -1517,6 +1600,10 @@ struct sockaddr_storage;
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
+# define strdup(s) unbound_stat_strdup_log(s, __FILE__, __LINE__, __func__)
+#ifdef HAVE_REALLOCARRAY
+# define reallocarray(p,n,s) unbound_stat_reallocarray_log(p, n, s, __FILE__, __LINE__, __func__)
+#endif
void *unbound_stat_malloc(size_t size);
void *unbound_stat_calloc(size_t nmemb, size_t size);
void unbound_stat_free(void *ptr);
@@ -1529,6 +1616,10 @@ void unbound_stat_free_log(void *ptr, const char* file, int line,
const char* func);
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
int line, const char* func);
+void *unbound_stat_reallocarray_log(void *ptr, size_t nmemb, size_t size,
+ const char* file, int line, const char* func);
+char *unbound_stat_strdup_log(const char *s, const char* file, int line,
+ const char* func);
#elif defined(UNBOUND_ALLOC_LITE)
# include "util/alloc.h"
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
diff --git a/lib/libutil/login.conf.5 b/lib/libutil/login.conf.5
index 27f37fb5fc30..942f3ecd2661 100644
--- a/lib/libutil/login.conf.5
+++ b/lib/libutil/login.conf.5
@@ -17,7 +17,7 @@
.\" 5. Modifications may be freely made to this file providing the above
.\" conditions are met.
.\"
-.Dd June 28, 2023
+.Dd September 25, 2025
.Dt LOGIN.CONF 5
.Os
.Sh NAME
@@ -496,7 +496,7 @@ lists.
.Xr pam 3 ,
.Xr passwd 5 ,
.Xr ttys 5 ,
-.Xr ftpd 8 ,
+.Xr ftpd 8 Pq Pa ports/ftp/freebsd-ftpd ,
.Xr pam_passwdqc 8
.Sh HISTORY
The file
diff --git a/lib/libxo/tests/encoder/Makefile b/lib/libxo/tests/encoder/Makefile
index 7522328b0818..02634b971ace 100644
--- a/lib/libxo/tests/encoder/Makefile
+++ b/lib/libxo/tests/encoder/Makefile
@@ -1,4 +1,5 @@
PACKAGE= tests
+NO_DEV_PACKAGE=
LIBXOSRC= ${SRCTOP}/contrib/libxo
diff --git a/lib/liby/Makefile b/lib/liby/Makefile
index 93f72ee440f8..ace8f8457d22 100644
--- a/lib/liby/Makefile
+++ b/lib/liby/Makefile
@@ -1,4 +1,4 @@
-PACKAGE=lib${LIB}
+PACKAGE=toolchain
LIB= y
SRCS= main.c yyerror.c
NO_PIC=
diff --git a/lib/msun/src/s_cpow.c b/lib/msun/src/s_cpow.c
index b887db51aa2a..2c20a8f3b48b 100644
--- a/lib/msun/src/s_cpow.c
+++ b/lib/msun/src/s_cpow.c
@@ -58,7 +58,10 @@ cpow(double complex a, double complex z)
y = cimag (z);
absa = cabs (a);
if (absa == 0.0) {
- return (CMPLX(0.0, 0.0));
+ if (x == 0 && y == 0)
+ return (CMPLX(1., 0.));
+ else
+ return (CMPLX(0., 0.));
}
arga = carg (a);
r = pow (absa, x);
diff --git a/lib/msun/src/s_cpowf.c b/lib/msun/src/s_cpowf.c
index 144291079f97..b8bdbd9cb07b 100644
--- a/lib/msun/src/s_cpowf.c
+++ b/lib/msun/src/s_cpowf.c
@@ -57,7 +57,10 @@ cpowf(float complex a, float complex z)
y = cimagf(z);
absa = cabsf (a);
if (absa == 0.0f) {
- return (CMPLXF(0.0f, 0.0f));
+ if (x == 0 && y == 0)
+ return (CMPLXF(1.f, 0.f));
+ else
+ return (CMPLXF(0.f, 0.f));
}
arga = cargf (a);
r = powf (absa, x);
diff --git a/lib/msun/src/s_cpowl.c b/lib/msun/src/s_cpowl.c
index 39797cadcfcb..efbe4936895f 100644
--- a/lib/msun/src/s_cpowl.c
+++ b/lib/msun/src/s_cpowl.c
@@ -57,7 +57,10 @@ cpowl(long double complex a, long double complex z)
y = cimagl(z);
absa = cabsl(a);
if (absa == 0.0L) {
- return (CMPLXL(0.0L, 0.0L));
+ if (x == 0 && y == 0)
+ return (CMPLXL(1.L, 0.L));
+ else
+ return (CMPLXL(0.L, 0.L));
}
arga = cargl(a);
r = powl(absa, x);
diff --git a/lib/ncurses/Makefile.inc b/lib/ncurses/Makefile.inc
index f2ed84e2e38f..eea49908474c 100644
--- a/lib/ncurses/Makefile.inc
+++ b/lib/ncurses/Makefile.inc
@@ -1,5 +1,6 @@
# This is to include src/lib/Makefile.inc
+PACKAGE?= ncurses
WARNS?= 3
.include "../Makefile.inc"
diff --git a/lib/ncurses/form/Makefile b/lib/ncurses/form/Makefile
index d4774a5f51a8..7d8963b05ae8 100644
--- a/lib/ncurses/form/Makefile
+++ b/lib/ncurses/form/Makefile
@@ -3,7 +3,6 @@
SRCDIR= ${NCURSES_DIR}/form
-PACKAGE= clibs
LIB= formw
SHLIB_MAJOR= 6
diff --git a/lib/ncurses/ncurses/Makefile b/lib/ncurses/ncurses/Makefile
index 512a452ad6d0..b60760281b39 100644
--- a/lib/ncurses/ncurses/Makefile
+++ b/lib/ncurses/ncurses/Makefile
@@ -1,4 +1,3 @@
-PACKAGE= clibs
SHLIBDIR?= /lib
.include <src.opts.mk>
diff --git a/lib/ncurses/panel/Makefile b/lib/ncurses/panel/Makefile
index a51129df42e3..dfb478aa5f5b 100644
--- a/lib/ncurses/panel/Makefile
+++ b/lib/ncurses/panel/Makefile
@@ -3,7 +3,6 @@
SRCDIR= ${NCURSES_DIR}/panel
-PACKAGE= clibs
LIB= panelw
SHLIB_MAJOR= 6
diff --git a/lib/ncurses/tinfo/Makefile b/lib/ncurses/tinfo/Makefile
index 476df54bb72a..8f01557edaee 100644
--- a/lib/ncurses/tinfo/Makefile
+++ b/lib/ncurses/tinfo/Makefile
@@ -1,4 +1,3 @@
-PACKAGE= clibs
SHLIBDIR?= /lib
.include <src.opts.mk>
diff --git a/lib/nss_tacplus/Makefile b/lib/nss_tacplus/Makefile
index f39788cfbdea..a969cd85778d 100644
--- a/lib/nss_tacplus/Makefile
+++ b/lib/nss_tacplus/Makefile
@@ -1,5 +1,5 @@
LIB= nss_tacplus
-SRCS= ${LIB}.8
+SRCS= ${LIB}.c
SHLIB_MAJOR= 1
SHLIB_NAME= ${LIB}.so.${SHLIB_MAJOR}
LIBADD= tacplus
diff --git a/lib/virtual_oss/Makefile b/lib/virtual_oss/Makefile
new file mode 100644
index 000000000000..dc83edd4b980
--- /dev/null
+++ b/lib/virtual_oss/Makefile
@@ -0,0 +1,9 @@
+.include <src.opts.mk>
+
+SHLIBDIR?= ${LIBDIR}/virtual_oss
+
+SUBDIR+= null \
+ oss
+
+.include "Makefile.inc"
+.include <bsd.subdir.mk>
diff --git a/lib/virtual_oss/Makefile.inc b/lib/virtual_oss/Makefile.inc
new file mode 100644
index 000000000000..45c8e0b1fdfc
--- /dev/null
+++ b/lib/virtual_oss/Makefile.inc
@@ -0,0 +1,3 @@
+.include "../Makefile.inc"
+
+LDFLAGS+= -L${.OBJDIR:H:H}/libsamplerate
diff --git a/lib/virtual_oss/bt/Makefile b/lib/virtual_oss/bt/Makefile
new file mode 100644
index 000000000000..15413b7a1f1e
--- /dev/null
+++ b/lib/virtual_oss/bt/Makefile
@@ -0,0 +1,19 @@
+SHLIB_NAME= voss_bt.so
+SHLIBDIR= ${LIBDIR}/virtual_oss
+
+SRCS= bt.c \
+ avdtp.c \
+ sbc_encode.c
+
+CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \
+ -I${SRCTOP}/contrib/libsamplerate
+LDFLAGS+= -lbluetooth -lsdp
+LIBADD= samplerate
+
+.if defined(HAVE_LIBAV)
+CFLAGS+= -I${LOCALBASE:U/usr/local}/include -DHAVE_LIBAV
+LDFLAGS+= -L${LOCALBASE:U/usr/local}/lib \
+ -lavdevice -lavutil -lavcodec -lavformat
+.endif
+
+.include <bsd.lib.mk>
diff --git a/lib/virtual_oss/bt/avdtp.c b/lib/virtual_oss/bt/avdtp.c
new file mode 100644
index 000000000000..82ed0fb942b6
--- /dev/null
+++ b/lib/virtual_oss/bt/avdtp.c
@@ -0,0 +1,720 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2015-2016 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ * Copyright (c) 2016-2019 Hans Petter Selasky <hps@selasky.org>
+ * Copyright (c) 2019 Google LLC, written by Richard Kralovic <riso@google.com>
+ *
+ * This software is dedicated to the memory of -
+ * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
+ *
+ * Barry was a man who loved his music.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/uio.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "avdtp_signal.h"
+#include "bt.h"
+
+#define DPRINTF(...) printf("backend_bt: " __VA_ARGS__)
+
+struct avdtpGetPacketInfo {
+ uint8_t buffer_data[512];
+ uint16_t buffer_len;
+ uint8_t trans;
+ uint8_t signalID;
+};
+
+static int avdtpAutoConfig(struct bt_config *);
+
+/* Return received message type if success, < 0 if failure. */
+static int
+avdtpGetPacket(int fd, struct avdtpGetPacketInfo *info)
+{
+ uint8_t *pos = info->buffer_data;
+ uint8_t *end = info->buffer_data + sizeof(info->buffer_data);
+ uint8_t message_type;
+ int len;
+
+ memset(info, 0, sizeof(*info));
+
+ /* Handle fragmented packets */
+ for (int remaining = 1; remaining > 0; --remaining) {
+ len = read(fd, pos, end - pos);
+
+ if (len < AVDTP_LEN_SUCCESS)
+ return (-1);
+ if (len == (int)(end - pos))
+ return (-1); /* buffer too small */
+
+ uint8_t trans = (pos[0] & TRANSACTIONLABEL) >> TRANSACTIONLABEL_S;
+ uint8_t packet_type = (pos[0] & PACKETTYPE) >> PACKETTYPE_S;
+ uint8_t current_message_type = (info->buffer_data[0] & MESSAGETYPE);
+ uint8_t shift;
+ if (pos == info->buffer_data) {
+ info->trans = trans;
+ message_type = current_message_type;
+ if (packet_type == singlePacket) {
+ info->signalID = (pos[1] & SIGNALID_MASK);
+ shift = 2;
+ } else {
+ if (packet_type != startPacket)
+ return (-1);
+ remaining = pos[1];
+ info->signalID = (pos[2] & SIGNALID_MASK);
+ shift = 3;
+ }
+ } else {
+ if (info->trans != trans ||
+ message_type != current_message_type ||
+ (remaining == 1 && packet_type != endPacket) ||
+ (remaining > 1 && packet_type != continuePacket)) {
+ return (-1);
+ }
+ shift = 1;
+ }
+ memmove(pos, pos + shift, len);
+ pos += len;
+ }
+ info->buffer_len = pos - info->buffer_data;
+ return (message_type);
+}
+
+/* Returns 0 on success, < 0 on failure. */
+static int
+avdtpSendPacket(int fd, uint8_t command, uint8_t trans, uint8_t type,
+ uint8_t * data0, int datasize0, uint8_t * data1,
+ int datasize1)
+{
+ struct iovec iov[3];
+ uint8_t header[2];
+ int retval;
+
+ /* fill out command header */
+ header[0] = (trans << 4) | (type & 3);
+ if (command != 0)
+ header[1] = command & 0x3f;
+ else
+ header[1] = 3;
+
+ iov[0].iov_base = header;
+ iov[0].iov_len = 2;
+ iov[1].iov_base = data0;
+ iov[1].iov_len = datasize0;
+ iov[2].iov_base = data1;
+ iov[2].iov_len = datasize1;
+
+ retval = writev(fd, iov, 3);
+ if (retval != (2 + datasize0 + datasize1))
+ return (-EINVAL);
+ else
+ return (0);
+}
+
+/* Returns 0 on success, < 0 on failure. */
+static int
+avdtpSendSyncCommand(int fd, struct avdtpGetPacketInfo *info,
+ uint8_t command, uint8_t type, uint8_t * data0,
+ int datasize0, uint8_t * data1, int datasize1)
+{
+ static uint8_t transLabel;
+ uint8_t trans;
+ int retval;
+
+ alarm(8); /* set timeout */
+
+ trans = (transLabel++) & 0xF;
+
+ retval = avdtpSendPacket(fd, command, trans, type,
+ data0, datasize0, data1, datasize1);
+ if (retval)
+ goto done;
+retry:
+ switch (avdtpGetPacket(fd, info)) {
+ case RESPONSEACCEPT:
+ if (info->trans != trans)
+ goto retry;
+ retval = 0;
+ break;
+ case RESPONSEREJECT:
+ if (info->trans != trans)
+ goto retry;
+ retval = -EINVAL;
+ break;
+ case COMMAND:
+ retval = avdtpSendReject(fd, info->trans, info->signalID);
+ if (retval == 0)
+ goto retry;
+ break;
+ default:
+ retval = -ENXIO;
+ break;
+ }
+done:
+ alarm(0); /* clear timeout */
+
+ return (retval);
+}
+
+/*
+ * Variant for acceptor role: We support any frequency, blocks, bands, and
+ * allocation. Returns 0 on success, < 0 on failure.
+ */
+static int
+avdtpSendCapabilitiesResponseSBCForACP(int fd, int trans)
+{
+ uint8_t data[10];
+
+ data[0] = mediaTransport;
+ data[1] = 0;
+ data[2] = mediaCodec;
+ data[3] = 0x6;
+ data[4] = mediaTypeAudio;
+ data[5] = SBC_CODEC_ID;
+ data[6] =
+ (1 << (3 - MODE_STEREO)) |
+ (1 << (3 - MODE_JOINT)) |
+ (1 << (3 - MODE_DUAL)) |
+ (1 << (3 - MODE_MONO)) |
+ (1 << (7 - FREQ_44_1K)) |
+ (1 << (7 - FREQ_48K)) |
+ (1 << (7 - FREQ_32K)) |
+ (1 << (7 - FREQ_16K));
+ data[7] =
+ (1 << (7 - BLOCKS_4)) |
+ (1 << (7 - BLOCKS_8)) |
+ (1 << (7 - BLOCKS_12)) |
+ (1 << (7 - BLOCKS_16)) |
+ (1 << (3 - BANDS_4)) |
+ (1 << (3 - BANDS_8)) | (1 << ALLOC_LOUDNESS) | (1 << ALLOC_SNR);
+ data[8] = MIN_BITPOOL;
+ data[9] = DEFAULT_MAXBPOOL;
+
+ return (avdtpSendPacket(fd, AVDTP_GET_CAPABILITIES, trans,
+ RESPONSEACCEPT, data, sizeof(data), NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpSendAccept(int fd, uint8_t trans, uint8_t myCommand)
+{
+ return (avdtpSendPacket(fd, myCommand, trans, RESPONSEACCEPT,
+ NULL, 0, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpSendReject(int fd, uint8_t trans, uint8_t myCommand)
+{
+ uint8_t value = 0;
+
+ return (avdtpSendPacket(fd, myCommand, trans, RESPONSEREJECT,
+ &value, 1, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpSendDiscResponseAudio(int fd, uint8_t trans,
+ uint8_t mySep, uint8_t is_sink)
+{
+ uint8_t data[2];
+
+ data[0] = mySep << 2;
+ data[1] = mediaTypeAudio << 4 | (is_sink ? (1 << 3) : 0);
+
+ return (avdtpSendPacket(fd, AVDTP_DISCOVER, trans, RESPONSEACCEPT,
+ data, 2, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpDiscoverAndConfig(struct bt_config *cfg, bool isSink)
+{
+ struct avdtpGetPacketInfo info;
+ uint16_t offset;
+ uint8_t chmode = cfg->chmode;
+ uint8_t aacMode1 = cfg->aacMode1;
+ uint8_t aacMode2 = cfg->aacMode2;
+ int retval;
+
+ retval = avdtpSendSyncCommand(cfg->hc, &info, AVDTP_DISCOVER, 0,
+ NULL, 0, NULL, 0);
+ if (retval)
+ return (retval);
+
+ retval = -EBUSY;
+ for (offset = 0; offset + 2 <= info.buffer_len; offset += 2) {
+ cfg->sep = info.buffer_data[offset] >> 2;
+ cfg->media_Type = info.buffer_data[offset + 1] >> 4;
+ cfg->chmode = chmode;
+ cfg->aacMode1 = aacMode1;
+ cfg->aacMode2 = aacMode2;
+ if (info.buffer_data[offset] & DISCOVER_SEP_IN_USE)
+ continue;
+ if (info.buffer_data[offset + 1] & DISCOVER_IS_SINK) {
+ if (!isSink)
+ continue;
+ } else {
+ if (isSink)
+ continue;
+ }
+ /* try to configure SBC */
+ retval = avdtpAutoConfig(cfg);
+ if (retval == 0)
+ return (0);
+ }
+ return (retval);
+}
+
+/* Returns 0 on success, < 0 on failure. */
+static int
+avdtpGetCapabilities(int fd, uint8_t sep, struct avdtpGetPacketInfo *info)
+{
+ uint8_t address = (sep << 2);
+
+ return (avdtpSendSyncCommand(fd, info,
+ AVDTP_GET_CAPABILITIES, 0, &address, 1,
+ NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpSetConfiguration(int fd, uint8_t sep, uint8_t * data, int datasize)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t configAddresses[2];
+
+ configAddresses[0] = sep << 2;
+ configAddresses[1] = INTSEP << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_SET_CONFIGURATION, 0,
+ configAddresses, 2, data, datasize));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpOpen(int fd, uint8_t sep)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t address = sep << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_OPEN, 0,
+ &address, 1, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpStart(int fd, uint8_t sep)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t address = sep << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_START, 0,
+ &address, 1, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpClose(int fd, uint8_t sep)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t address = sep << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_CLOSE, 0,
+ &address, 1, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpSuspend(int fd, uint8_t sep)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t address = sep << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_SUSPEND, 0,
+ &address, 1, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpAbort(int fd, uint8_t sep)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t address = sep << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_ABORT, 0,
+ &address, 1, NULL, 0));
+}
+
+static int
+avdtpAutoConfig(struct bt_config *cfg)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t freqmode;
+ uint8_t blk_len_sb_alloc;
+ uint8_t availFreqMode = 0;
+ uint8_t availConfig = 0;
+ uint8_t supBitpoolMin = 0;
+ uint8_t supBitpoolMax = 0;
+ uint8_t aacMode1 = 0;
+ uint8_t aacMode2 = 0;
+#ifdef HAVE_LIBAV
+ uint8_t aacBitrate3 = 0;
+ uint8_t aacBitrate4 = 0;
+ uint8_t aacBitrate5 = 0;
+#endif
+ int retval;
+ int i;
+
+ retval = avdtpGetCapabilities(cfg->hc, cfg->sep, &info);
+ if (retval) {
+ DPRINTF("Cannot get capabilities\n");
+ return (retval);
+ }
+retry:
+ for (i = 0; (i + 1) < info.buffer_len;) {
+#if 0
+ DPRINTF("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ info.buffer_data[i + 0],
+ info.buffer_data[i + 1],
+ info.buffer_data[i + 2],
+ info.buffer_data[i + 3],
+ info.buffer_data[i + 4], info.buffer_data[i + 5]);
+#endif
+ if (i + 2 + info.buffer_data[i + 1] > info.buffer_len)
+ break;
+ switch (info.buffer_data[i]) {
+ case mediaTransport:
+ break;
+ case mediaCodec:
+ if (info.buffer_data[i + 1] < 2)
+ break;
+ /* check codec */
+ switch (info.buffer_data[i + 3]) {
+ case 0: /* SBC */
+ if (info.buffer_data[i + 1] < 6)
+ break;
+ availFreqMode = info.buffer_data[i + 4];
+ availConfig = info.buffer_data[i + 5];
+ supBitpoolMin = info.buffer_data[i + 6];
+ supBitpoolMax = info.buffer_data[i + 7];
+ break;
+ case 2: /* MPEG2/4 AAC */
+ if (info.buffer_data[i + 1] < 8)
+ break;
+ aacMode1 = info.buffer_data[i + 5];
+ aacMode2 = info.buffer_data[i + 6];
+#ifdef HAVE_LIBAV
+ aacBitrate3 = info.buffer_data[i + 7];
+ aacBitrate4 = info.buffer_data[i + 8];
+ aacBitrate5 = info.buffer_data[i + 9];
+#endif
+ break;
+ default:
+ break;
+ }
+ }
+ /* jump to next information element */
+ i += 2 + info.buffer_data[i + 1];
+ }
+ aacMode1 &= cfg->aacMode1;
+ aacMode2 &= cfg->aacMode2;
+
+ /* Try AAC first */
+ if (aacMode1 == cfg->aacMode1 && aacMode2 == cfg->aacMode2) {
+#ifdef HAVE_LIBAV
+ uint8_t config[12] = { mediaTransport, 0x0, mediaCodec,
+ 0x8, 0x0, 0x02, 0x80, aacMode1, aacMode2, aacBitrate3,
+ aacBitrate4, aacBitrate5
+ };
+
+ if (avdtpSetConfiguration
+ (cfg->hc, cfg->sep, config, sizeof(config)) == 0) {
+ cfg->codec = CODEC_AAC;
+ return (0);
+ }
+#endif
+ }
+ /* Try SBC second */
+ if (cfg->freq == FREQ_UNDEFINED)
+ goto auto_config_failed;
+
+ freqmode = (1 << (3 - cfg->freq + 4)) | (1 << (3 - cfg->chmode));
+
+ if ((availFreqMode & freqmode) != freqmode) {
+ DPRINTF("No frequency and mode match\n");
+ goto auto_config_failed;
+ }
+ for (i = 0; i != 4; i++) {
+ blk_len_sb_alloc = (1 << (i + 4)) |
+ (1 << (1 - cfg->bands + 2)) | (1 << cfg->allocm);
+
+ if ((availConfig & blk_len_sb_alloc) == blk_len_sb_alloc)
+ break;
+ }
+ if (i == 4) {
+ DPRINTF("No bands available\n");
+ goto auto_config_failed;
+ }
+ cfg->blocks = (3 - i);
+
+ if (cfg->allocm == ALLOC_SNR)
+ supBitpoolMax &= ~1;
+
+ if (cfg->chmode == MODE_DUAL || cfg->chmode == MODE_MONO)
+ supBitpoolMax /= 2;
+
+ if (cfg->bands == BANDS_4)
+ supBitpoolMax /= 2;
+
+ if (supBitpoolMax > cfg->bitpool)
+ supBitpoolMax = cfg->bitpool;
+ else
+ cfg->bitpool = supBitpoolMax;
+
+ do {
+ uint8_t config[10] = { mediaTransport, 0x0, mediaCodec, 0x6,
+ 0x0, 0x0, freqmode, blk_len_sb_alloc, supBitpoolMin,
+ supBitpoolMax
+ };
+
+ if (avdtpSetConfiguration
+ (cfg->hc, cfg->sep, config, sizeof(config)) == 0) {
+ cfg->codec = CODEC_SBC;
+ return (0);
+ }
+ } while (0);
+
+auto_config_failed:
+ if (cfg->chmode == MODE_STEREO) {
+ cfg->chmode = MODE_MONO;
+ cfg->aacMode2 ^= 0x0C;
+ goto retry;
+ }
+ return (-EINVAL);
+}
+
+void
+avdtpACPFree(struct bt_config *cfg)
+{
+ if (cfg->handle.sbc_enc) {
+ free(cfg->handle.sbc_enc);
+ cfg->handle.sbc_enc = NULL;
+ }
+}
+
+/* Returns 0 on success, < 0 on failure. */
+static int
+avdtpParseSBCConfig(uint8_t * data, struct bt_config *cfg)
+{
+ if (data[0] & (1 << (7 - FREQ_48K))) {
+ cfg->freq = FREQ_48K;
+ } else if (data[0] & (1 << (7 - FREQ_44_1K))) {
+ cfg->freq = FREQ_44_1K;
+ } else if (data[0] & (1 << (7 - FREQ_32K))) {
+ cfg->freq = FREQ_32K;
+ } else if (data[0] & (1 << (7 - FREQ_16K))) {
+ cfg->freq = FREQ_16K;
+ } else {
+ return -EINVAL;
+ }
+
+ if (data[0] & (1 << (3 - MODE_STEREO))) {
+ cfg->chmode = MODE_STEREO;
+ } else if (data[0] & (1 << (3 - MODE_JOINT))) {
+ cfg->chmode = MODE_JOINT;
+ } else if (data[0] & (1 << (3 - MODE_DUAL))) {
+ cfg->chmode = MODE_DUAL;
+ } else if (data[0] & (1 << (3 - MODE_MONO))) {
+ cfg->chmode = MODE_MONO;
+ } else {
+ return -EINVAL;
+ }
+
+ if (data[1] & (1 << (7 - BLOCKS_16))) {
+ cfg->blocks = BLOCKS_16;
+ } else if (data[1] & (1 << (7 - BLOCKS_12))) {
+ cfg->blocks = BLOCKS_12;
+ } else if (data[1] & (1 << (7 - BLOCKS_8))) {
+ cfg->blocks = BLOCKS_8;
+ } else if (data[1] & (1 << (7 - BLOCKS_4))) {
+ cfg->blocks = BLOCKS_4;
+ } else {
+ return -EINVAL;
+ }
+
+ if (data[1] & (1 << (3 - BANDS_8))) {
+ cfg->bands = BANDS_8;
+ } else if (data[1] & (1 << (3 - BANDS_4))) {
+ cfg->bands = BANDS_4;
+ } else {
+ return -EINVAL;
+ }
+
+ if (data[1] & (1 << ALLOC_LOUDNESS)) {
+ cfg->allocm = ALLOC_LOUDNESS;
+ } else if (data[1] & (1 << ALLOC_SNR)) {
+ cfg->allocm = ALLOC_SNR;
+ } else {
+ return -EINVAL;
+ }
+ cfg->bitpool = data[3];
+ return 0;
+}
+
+int
+avdtpACPHandlePacket(struct bt_config *cfg)
+{
+ struct avdtpGetPacketInfo info;
+ int retval;
+
+ if (avdtpGetPacket(cfg->hc, &info) != COMMAND)
+ return (-ENXIO);
+
+ switch (info.signalID) {
+ case AVDTP_DISCOVER:
+ retval =
+ avdtpSendDiscResponseAudio(cfg->hc, info.trans, ACPSEP, 1);
+ if (!retval)
+ retval = AVDTP_DISCOVER;
+ break;
+ case AVDTP_GET_CAPABILITIES:
+ retval =
+ avdtpSendCapabilitiesResponseSBCForACP(cfg->hc, info.trans);
+ if (!retval)
+ retval = AVDTP_GET_CAPABILITIES;
+ break;
+ case AVDTP_SET_CONFIGURATION:
+ if (cfg->acceptor_state != acpInitial)
+ goto err;
+ cfg->sep = info.buffer_data[1] >> 2;
+ int is_configured = 0;
+ for (int i = 2; (i + 1) < info.buffer_len;) {
+ if (i + 2 + info.buffer_data[i + 1] > info.buffer_len)
+ break;
+ switch (info.buffer_data[i]) {
+ case mediaTransport:
+ break;
+ case mediaCodec:
+ if (info.buffer_data[i + 1] < 2)
+ break;
+ /* check codec */
+ switch (info.buffer_data[i + 3]) {
+ case 0: /* SBC */
+ if (info.buffer_data[i + 1] < 6)
+ break;
+ retval =
+ avdtpParseSBCConfig(info.buffer_data + i + 4, cfg);
+ if (retval)
+ return retval;
+ is_configured = 1;
+ break;
+ case 2: /* MPEG2/4 AAC */
+ /* TODO: Add support */
+ default:
+ break;
+ }
+ }
+ /* jump to next information element */
+ i += 2 + info.buffer_data[i + 1];
+ }
+ if (!is_configured)
+ goto err;
+
+ retval =
+ avdtpSendAccept(cfg->hc, info.trans, AVDTP_SET_CONFIGURATION);
+ if (retval)
+ return (retval);
+
+ /* TODO: Handle other codecs */
+ if (cfg->handle.sbc_enc == NULL) {
+ cfg->handle.sbc_enc = malloc(sizeof(*cfg->handle.sbc_enc));
+ if (cfg->handle.sbc_enc == NULL)
+ return (-ENOMEM);
+ }
+ memset(cfg->handle.sbc_enc, 0, sizeof(*cfg->handle.sbc_enc));
+
+ retval = AVDTP_SET_CONFIGURATION;
+ cfg->acceptor_state = acpConfigurationSet;
+ break;
+ case AVDTP_OPEN:
+ if (cfg->acceptor_state != acpConfigurationSet)
+ goto err;
+ retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID);
+ if (retval)
+ return (retval);
+ retval = info.signalID;
+ cfg->acceptor_state = acpStreamOpened;
+ break;
+ case AVDTP_START:
+ if (cfg->acceptor_state != acpStreamOpened &&
+ cfg->acceptor_state != acpStreamSuspended) {
+ goto err;
+ }
+ retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID);
+ if (retval)
+ return retval;
+ retval = info.signalID;
+ cfg->acceptor_state = acpStreamStarted;
+ break;
+ case AVDTP_CLOSE:
+ if (cfg->acceptor_state != acpStreamOpened &&
+ cfg->acceptor_state != acpStreamStarted &&
+ cfg->acceptor_state != acpStreamSuspended) {
+ goto err;
+ }
+ retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID);
+ if (retval)
+ return (retval);
+ retval = info.signalID;
+ cfg->acceptor_state = acpStreamClosed;
+ break;
+ case AVDTP_SUSPEND:
+ if (cfg->acceptor_state != acpStreamOpened &&
+ cfg->acceptor_state != acpStreamStarted) {
+ goto err;
+ }
+ retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID);
+ if (retval)
+ return (retval);
+ retval = info.signalID;
+ cfg->acceptor_state = acpStreamSuspended;
+ break;
+ case AVDTP_GET_CONFIGURATION:
+ case AVDTP_RECONFIGURE:
+ case AVDTP_ABORT:
+ /* TODO: Implement this. */
+ default:
+err:
+ avdtpSendReject(cfg->hc, info.trans, info.signalID);
+ return (-ENXIO);
+ }
+ return (retval);
+}
diff --git a/lib/virtual_oss/bt/avdtp_signal.h b/lib/virtual_oss/bt/avdtp_signal.h
new file mode 100644
index 000000000000..a46cc6dd9dcf
--- /dev/null
+++ b/lib/virtual_oss/bt/avdtp_signal.h
@@ -0,0 +1,139 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ *
+ * This software is dedicated to the memory of -
+ * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
+ *
+ * Barry was a man who loved his music.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _AVDTP_SIGNAL_H_
+#define _AVDTP_SIGNAL_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* Our endpoint. */
+#define INTSEP 8
+#define ACPSEP 8
+
+/* AVDTP signals. */
+
+#define AVDTP_DISCOVER 0x01
+#define AVDTP_GET_CAPABILITIES 0x02
+#define AVDTP_SET_CONFIGURATION 0x03
+#define AVDTP_GET_CONFIGURATION 0x04
+#define AVDTP_RECONFIGURE 0x05
+#define AVDTP_OPEN 0x06
+#define AVDTP_START 0x07
+#define AVDTP_CLOSE 0x08
+#define AVDTP_SUSPEND 0x09
+#define AVDTP_ABORT 0x0a
+#define AVDTP_SECUURITY_CONTROL 0x0b
+
+/* Signal Command & Response Header Masks. */
+
+#define TRANSACTIONLABEL 0xf0
+#define TRANSACTIONLABEL_S 4
+#define SIGNALID_MASK 0x3f
+#define PACKETTYPE 0x0c
+#define PACKETTYPE_S 0x02
+#define MESSAGETYPE 0x03
+#define SIGNALIDENTIFIER 0x3f
+#define DISCOVER_SEP_IN_USE 0x02
+#define DISCOVER_IS_SINK 0x08
+
+/* Packet Types */
+#define singlePacket 0x0
+#define startPacket 0x1
+#define continuePacket 0x2
+#define endPacket 0x3
+
+/* Message Types */
+#define COMMAND 0x0
+#define RESPONSEACCEPT 0x2
+#define RESPONSEREJECT 0x3
+
+/* Response general error/success lengths */
+#define AVDTP_LEN_SUCCESS 2
+#define AVDTP_LEN_ERROR 3
+
+/* Error codes */
+#define BAD_HEADER_FORMAT 0x01
+#define BAD_LENGTH 0x11
+#define BAD_ACP_SEID 0x12
+#define SEP_IN_USE 0x13
+#define SEP_NOT_IN_USE 0x14
+#define BAD_SERV_CATAGORY 0x17
+#define BAD_PAYLOAD_FORMAT 0x18
+#define NOT_SUPPORTED_COMMAND 0x19
+#define INVALID_CAPABILITIES 0x1a
+
+#define BAD_RECOVERY_TYPE 0x22
+#define BAD_MEDIA_TRANSPORT_FORMAT 0x23
+#define BAD_RECOVERY_FORMAT 0x25
+#define BAD_ROHC_FORMAT 0x26
+#define BAD_CP_FORMAT 0x27
+#define BAD_MULTIPLEXING_FORMAT 0x28
+#define UNSUPPORTED_CONFIGURATION 0x29
+#define BAD_STATE 0x31
+
+/* Service Capabilities Field. */
+#define mediaTransport 0x1
+#define reporting 0x2
+#define recovery 0x3
+#define contentProtection 0x4
+#define headerCompression 0x5
+#define multiplexing 0x6
+#define mediaCodec 0x7
+
+/* Media Codec Capabilities */
+#define mediaCodecSbc 0x00
+#define mediaCodecMpeg1 0x01
+#define mediaCodecMpeg2 0x02
+
+#define SBC_CODEC_ID 0x0
+#define mediaTypeAudio 0x0
+
+struct bt_config;
+
+int avdtpSendAccept(int, uint8_t, uint8_t);
+int avdtpSendReject(int, uint8_t, uint8_t);
+int avdtpSendDiscResponseAudio(int, uint8_t, uint8_t, uint8_t);
+int avdtpDiscoverAndConfig(struct bt_config *, bool);
+int avdtpSetConfiguration(int, uint8_t, uint8_t *, int);
+int avdtpOpen(int, uint8_t);
+int avdtpStart(int, uint8_t);
+int avdtpClose(int, uint8_t);
+int avdtpSuspend(int, uint8_t);
+int avdtpAbort(int, uint8_t);
+
+/* Return < 0 if error, processed signal otherwise. */
+int avdtpACPHandlePacket(struct bt_config *cfg);
+/* Free state allocated in avdtpACPHandlePacket(), if any. */
+void avdtpACPFree(struct bt_config *cfg);
+
+#endif /* _AVDTP_SIGNAL_H_ */
diff --git a/lib/virtual_oss/bt/bt.c b/lib/virtual_oss/bt/bt.c
new file mode 100644
index 000000000000..57f000b067d5
--- /dev/null
+++ b/lib/virtual_oss/bt/bt.c
@@ -0,0 +1,1061 @@
+/*-
+ * Copyright (c) 2015-2019 Hans Petter Selasky
+ * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ * Copyright (c) 2006 Itronix Inc
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/filio.h>
+#include <sys/soundcard.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#define L2CAP_SOCKET_CHECKED
+#include <bluetooth.h>
+#include <sdp.h>
+
+#include "backend.h"
+#include "int.h"
+
+#include "avdtp_signal.h"
+#include "bt.h"
+
+#define DPRINTF(...) printf("backend_bt: " __VA_ARGS__)
+
+struct l2cap_info {
+ bdaddr_t laddr;
+ bdaddr_t raddr;
+};
+
+static struct bt_config bt_play_cfg;
+static struct bt_config bt_rec_cfg;
+
+int
+bt_receive(struct bt_config *cfg, void *ptr, int len, int use_delay)
+{
+ struct sbc_header *phdr = (struct sbc_header *)cfg->mtu_data;
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ uint8_t *tmp = ptr;
+ int old_len = len;
+ int delta;
+ int err;
+
+ /* wait for service interval, if any */
+ if (use_delay)
+ virtual_oss_wait();
+
+ switch (cfg->blocks) {
+ case BLOCKS_4:
+ sbc->blocks = 4;
+ break;
+ case BLOCKS_8:
+ sbc->blocks = 8;
+ break;
+ case BLOCKS_12:
+ sbc->blocks = 12;
+ break;
+ default:
+ sbc->blocks = 16;
+ break;
+ }
+
+ switch (cfg->bands) {
+ case BANDS_4:
+ sbc->bands = 4;
+ break;
+ default:
+ sbc->bands = 8;
+ break;
+ }
+
+ if (cfg->chmode != MODE_MONO) {
+ sbc->channels = 2;
+ } else {
+ sbc->channels = 1;
+ }
+
+ while (1) {
+ delta = len & ~1;
+ if (delta > (int)(2 * sbc->rem_len))
+ delta = (2 * sbc->rem_len);
+
+ /* copy out samples, if any */
+ memcpy(tmp, (char *)sbc->music_data + sbc->rem_off, delta);
+ tmp += delta;
+ len -= delta;
+ sbc->rem_off += delta / 2;
+ sbc->rem_len -= delta / 2;
+ if (len == 0)
+ break;
+
+ if (sbc->rem_len == 0 &&
+ sbc->rem_data_frames != 0) {
+ err = sbc_decode_frame(cfg, sbc->rem_data_len * 8);
+ sbc->rem_data_frames--;
+ sbc->rem_data_ptr += err;
+ sbc->rem_data_len -= err;
+ continue;
+ }
+ /* TODO: Support fragmented SBC frames */
+ err = read(cfg->fd, cfg->mtu_data, cfg->mtu);
+
+ if (err == 0) {
+ break;
+ } else if (err < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ break;
+ else
+ return (-1); /* disconnected */
+ }
+
+ /* verify RTP header */
+ if (err < (int)sizeof(*phdr) || phdr->id != 0x80)
+ continue;
+
+ sbc->rem_data_frames = phdr->numFrames;
+ sbc->rem_data_ptr = (uint8_t *)(phdr + 1);
+ sbc->rem_data_len = err - sizeof(*phdr);
+ }
+ return (old_len - len);
+}
+
+static int
+bt_set_format(int *format)
+{
+ int value;
+
+ value = *format & AFMT_S16_NE;
+ if (value != 0) {
+ *format = value;
+ return (0);
+ }
+ return (-1);
+}
+
+static void
+bt_close(struct voss_backend *pbe)
+{
+ struct bt_config *cfg = pbe->arg;
+
+ if (cfg->hc > 0) {
+ avdtpAbort(cfg->hc, cfg->sep);
+ avdtpClose(cfg->hc, cfg->sep);
+ close(cfg->hc);
+ cfg->hc = -1;
+ }
+ if (cfg->fd > 0) {
+ close(cfg->fd);
+ cfg->fd = -1;
+ }
+}
+
+static void
+bt_play_close(struct voss_backend *pbe)
+{
+ struct bt_config *cfg = pbe->arg;
+
+ switch (cfg->codec) {
+ case CODEC_SBC:
+ if (cfg->handle.sbc_enc == NULL)
+ break;
+ free(cfg->handle.sbc_enc);
+ cfg->handle.sbc_enc = NULL;
+ break;
+#ifdef HAVE_LIBAV
+ case CODEC_AAC:
+ if (cfg->handle.av.context == NULL)
+ break;
+ av_free(cfg->rem_in_data);
+ av_frame_free(&cfg->handle.av.frame);
+ avcodec_close(cfg->handle.av.context);
+ avformat_free_context(cfg->handle.av.format);
+ cfg->handle.av.context = NULL;
+ break;
+#endif
+ default:
+ break;
+ }
+ return (bt_close(pbe));
+}
+
+static void
+bt_rec_close(struct voss_backend *pbe)
+{
+ struct bt_config *cfg = pbe->arg;
+
+ switch (cfg->codec) {
+ case CODEC_SBC:
+ break;
+#ifdef HAVE_LIBAV
+ case CODEC_AAC:
+ break;
+#endif
+
+ default:
+ break;
+ }
+ return (bt_close(pbe));
+}
+
+static const uint32_t bt_attrs[] = {
+ SDP_ATTR_RANGE(SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
+ SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST),
+};
+
+#define BT_NUM_VALUES 32
+#define BT_BUF_SIZE 32
+
+static int
+bt_find_psm(const uint8_t *start, const uint8_t *end)
+{
+ uint32_t type;
+ uint32_t len;
+ int protover = 0;
+ int psm = -1;
+
+ if ((end - start) < 2)
+ return (-1);
+
+ SDP_GET8(type, start);
+ switch (type) {
+ case SDP_DATA_SEQ8:
+ SDP_GET8(len, start);
+ break;
+
+ case SDP_DATA_SEQ16:
+ SDP_GET16(len, start);
+ break;
+
+ case SDP_DATA_SEQ32:
+ SDP_GET32(len, start);
+ break;
+
+ default:
+ return (-1);
+ }
+
+ while (start < end) {
+ SDP_GET8(type, start);
+ switch (type) {
+ case SDP_DATA_SEQ8:
+ SDP_GET8(len, start);
+ break;
+
+ case SDP_DATA_SEQ16:
+ SDP_GET16(len, start);
+ break;
+
+ case SDP_DATA_SEQ32:
+ SDP_GET32(len, start);
+ break;
+
+ default:
+ return (-1);
+ }
+ /* check range */
+ if (len > (uint32_t)(end - start))
+ break;
+
+ if (len >= 6) {
+ const uint8_t *ptr = start;
+
+ SDP_GET8(type, ptr);
+ if (type == SDP_DATA_UUID16) {
+ uint16_t temp;
+
+ SDP_GET16(temp, ptr);
+ switch (temp) {
+ case SDP_UUID_PROTOCOL_L2CAP:
+ SDP_GET8(type, ptr);
+ SDP_GET16(psm, ptr);
+ break;
+ case SDP_UUID_PROTOCOL_AVDTP:
+ SDP_GET8(type, ptr);
+ SDP_GET16(protover, ptr);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ start += len;
+
+ if (protover >= 0x0100 && psm > -1)
+ return (htole16(psm));
+ }
+ return (-1);
+}
+
+static int
+bt_query(struct l2cap_info *info, uint16_t service_class)
+{
+ sdp_attr_t values[BT_NUM_VALUES];
+ uint8_t buffer[BT_NUM_VALUES][BT_BUF_SIZE];
+ void *ss;
+ int psm = -1;
+ int n;
+
+ memset(buffer, 0, sizeof(buffer));
+ memset(values, 0, sizeof(values));
+
+ ss = sdp_open(&info->laddr, &info->raddr);
+ if (ss == NULL || sdp_error(ss) != 0) {
+ DPRINTF("Could not open SDP\n");
+ sdp_close(ss);
+ return (psm);
+ }
+ /* Initialize attribute values array */
+ for (n = 0; n != BT_NUM_VALUES; n++) {
+ values[n].flags = SDP_ATTR_INVALID;
+ values[n].vlen = BT_BUF_SIZE;
+ values[n].value = buffer[n];
+ }
+
+ /* Do SDP Service Search Attribute Request */
+ n = sdp_search(ss, 1, &service_class, 1, bt_attrs, BT_NUM_VALUES, values);
+ if (n != 0) {
+ DPRINTF("SDP search failed\n");
+ goto done;
+ }
+ /* Print attributes values */
+ for (n = 0; n != BT_NUM_VALUES; n++) {
+ if (values[n].flags != SDP_ATTR_OK)
+ break;
+ if (values[n].attr != SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST)
+ continue;
+ psm = bt_find_psm(values[n].value, values[n].value + values[n].vlen);
+ if (psm > -1)
+ break;
+ }
+done:
+ sdp_close(ss);
+ return (psm);
+}
+
+static int
+bt_open(struct voss_backend *pbe __unused, const char *devname, int samplerate,
+ int bufsize __unused, int *pchannels, int *pformat, struct bt_config *cfg,
+ int service_class, int isSink)
+{
+ struct sockaddr_l2cap addr;
+ struct l2cap_info info;
+ socklen_t mtusize = sizeof(uint16_t);
+ int tmpbitpool;
+ int l2cap_psm;
+ int temp;
+
+ memset(&info, 0, sizeof(info));
+
+ if (strstr(devname, "/dev/bluetooth/") != devname) {
+ printf("Invalid device name '%s'", devname);
+ goto error;
+ }
+ /* skip prefix */
+ devname += sizeof("/dev/bluetooth/") - 1;
+
+ if (!bt_aton(devname, &info.raddr)) {
+ struct hostent *he = NULL;
+
+ if ((he = bt_gethostbyname(devname)) == NULL) {
+ DPRINTF("Could not get host by name\n");
+ goto error;
+ }
+ bdaddr_copy(&info.raddr, (bdaddr_t *)he->h_addr);
+ }
+ switch (samplerate) {
+ case 8000:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0x80;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 11025:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0x40;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 12000:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0x20;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 16000:
+ cfg->freq = FREQ_16K;
+ cfg->aacMode1 = 0x10;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 22050:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0x08;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 24000:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0x04;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 32000:
+ cfg->freq = FREQ_32K;
+ cfg->aacMode1 = 0x02;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 44100:
+ cfg->freq = FREQ_44_1K;
+ cfg->aacMode1 = 0x01;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 48000:
+ cfg->freq = FREQ_48K;
+ cfg->aacMode1 = 0;
+ cfg->aacMode2 = 0x8C;
+ break;
+ case 64000:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0;
+ cfg->aacMode2 = 0x4C;
+ break;
+ case 88200:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0;
+ cfg->aacMode2 = 0x2C;
+ break;
+ case 96000:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0;
+ cfg->aacMode2 = 0x1C;
+ break;
+ default:
+ DPRINTF("Invalid samplerate %d", samplerate);
+ goto error;
+ }
+ cfg->bands = BANDS_8;
+ cfg->bitpool = 0;
+
+ switch (*pchannels) {
+ case 1:
+ cfg->aacMode2 &= 0xF8;
+ cfg->chmode = MODE_MONO;
+ break;
+ default:
+ cfg->aacMode2 &= 0xF4;
+ cfg->chmode = MODE_STEREO;
+ break;
+ }
+
+ cfg->allocm = ALLOC_LOUDNESS;
+
+ if (cfg->chmode == MODE_MONO || cfg->chmode == MODE_DUAL)
+ tmpbitpool = 16;
+ else
+ tmpbitpool = 32;
+
+ if (cfg->bands == BANDS_8)
+ tmpbitpool *= 8;
+ else
+ tmpbitpool *= 4;
+
+ if (tmpbitpool > DEFAULT_MAXBPOOL)
+ tmpbitpool = DEFAULT_MAXBPOOL;
+
+ cfg->bitpool = tmpbitpool;
+
+ if (bt_set_format(pformat)) {
+ DPRINTF("Unsupported sample format\n");
+ goto error;
+ }
+ l2cap_psm = bt_query(&info, service_class);
+ DPRINTF("PSM=0x%02x\n", l2cap_psm);
+ if (l2cap_psm < 0) {
+ DPRINTF("PSM not found\n");
+ goto error;
+ }
+ cfg->hc = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
+ if (cfg->hc < 0) {
+ DPRINTF("Could not create BT socket\n");
+ goto error;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.l2cap_len = sizeof(addr);
+ addr.l2cap_family = AF_BLUETOOTH;
+ bdaddr_copy(&addr.l2cap_bdaddr, &info.laddr);
+
+ if (bind(cfg->hc, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ DPRINTF("Could not bind to HC\n");
+ goto error;
+ }
+ bdaddr_copy(&addr.l2cap_bdaddr, &info.raddr);
+ addr.l2cap_psm = l2cap_psm;
+ if (connect(cfg->hc, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ DPRINTF("Could not connect to HC: %d\n", errno);
+ goto error;
+ }
+ if (avdtpDiscoverAndConfig(cfg, isSink)) {
+ DPRINTF("DISCOVER FAILED\n");
+ goto error;
+ }
+ if (avdtpOpen(cfg->hc, cfg->sep)) {
+ DPRINTF("OPEN FAILED\n");
+ goto error;
+ }
+ cfg->fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
+ if (cfg->fd < 0) {
+ DPRINTF("Could not create BT socket\n");
+ goto error;
+ }
+ memset(&addr, 0, sizeof(addr));
+
+ addr.l2cap_len = sizeof(addr);
+ addr.l2cap_family = AF_BLUETOOTH;
+ bdaddr_copy(&addr.l2cap_bdaddr, &info.laddr);
+
+ if (bind(cfg->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ DPRINTF("Could not bind\n");
+ goto error;
+ }
+ bdaddr_copy(&addr.l2cap_bdaddr, &info.raddr);
+ addr.l2cap_psm = l2cap_psm;
+ if (connect(cfg->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ DPRINTF("Could not connect: %d\n", errno);
+ goto error;
+ }
+ if (isSink) {
+ if (getsockopt(cfg->fd, SOL_L2CAP, SO_L2CAP_OMTU, &cfg->mtu, &mtusize) == -1) {
+ DPRINTF("Could not get MTU\n");
+ goto error;
+ }
+ temp = cfg->mtu * 16;
+ if (setsockopt(cfg->fd, SOL_SOCKET, SO_SNDBUF, &temp, sizeof(temp)) == -1) {
+ DPRINTF("Could not set send buffer size\n");
+ goto error;
+ }
+ temp = cfg->mtu;
+ if (setsockopt(cfg->fd, SOL_SOCKET, SO_SNDLOWAT, &temp, sizeof(temp)) == -1) {
+ DPRINTF("Could not set low water mark\n");
+ goto error;
+ }
+ } else {
+ if (getsockopt(cfg->fd, SOL_L2CAP, SO_L2CAP_IMTU, &cfg->mtu, &mtusize) == -1) {
+ DPRINTF("Could not get MTU\n");
+ goto error;
+ }
+ temp = cfg->mtu * 16;
+ if (setsockopt(cfg->fd, SOL_SOCKET, SO_RCVBUF, &temp, sizeof(temp)) == -1) {
+ DPRINTF("Could not set receive buffer size\n");
+ goto error;
+ }
+ temp = 1;
+ if (setsockopt(cfg->fd, SOL_SOCKET, SO_RCVLOWAT, &temp, sizeof(temp)) == -1) {
+ DPRINTF("Could not set low water mark\n");
+ goto error;
+ }
+ temp = 1;
+ if (ioctl(cfg->fd, FIONBIO, &temp) == -1) {
+ DPRINTF("Could not set non-blocking I/O for receive direction\n");
+ goto error;
+ }
+ }
+
+ if (avdtpStart(cfg->hc, cfg->sep)) {
+ DPRINTF("START FAILED\n");
+ goto error;
+ }
+ switch (cfg->chmode) {
+ case MODE_MONO:
+ *pchannels = 1;
+ break;
+ default:
+ *pchannels = 2;
+ break;
+ }
+ return (0);
+
+error:
+ if (cfg->hc > 0) {
+ close(cfg->hc);
+ cfg->hc = -1;
+ }
+ if (cfg->fd > 0) {
+ close(cfg->fd);
+ cfg->fd = -1;
+ }
+ return (-1);
+}
+
+static void
+bt_init_cfg(struct bt_config *cfg)
+{
+ memset(cfg, 0, sizeof(*cfg));
+}
+
+static int
+bt_rec_open(struct voss_backend *pbe, const char *devname, int samplerate,
+ int bufsize, int *pchannels, int *pformat)
+{
+ struct bt_config *cfg = pbe->arg;
+ int retval;
+
+ bt_init_cfg(cfg);
+
+ retval = bt_open(pbe, devname, samplerate, bufsize, pchannels, pformat,
+ cfg, SDP_SERVICE_CLASS_AUDIO_SOURCE, 0);
+ if (retval != 0)
+ return (retval);
+ return (0);
+}
+
+static int
+bt_play_open(struct voss_backend *pbe, const char *devname, int samplerate,
+ int bufsize, int *pchannels, int *pformat)
+{
+ struct bt_config *cfg = pbe->arg;
+ int retval;
+
+ bt_init_cfg(cfg);
+
+ retval = bt_open(pbe, devname, samplerate, bufsize, pchannels, pformat,
+ cfg, SDP_SERVICE_CLASS_AUDIO_SINK, 1);
+ if (retval != 0)
+ return (retval);
+
+ /* setup codec */
+ switch (cfg->codec) {
+ case CODEC_SBC:
+ cfg->handle.sbc_enc =
+ malloc(sizeof(*cfg->handle.sbc_enc));
+ if (cfg->handle.sbc_enc == NULL)
+ return (-1);
+ memset(cfg->handle.sbc_enc, 0, sizeof(*cfg->handle.sbc_enc));
+ break;
+#ifdef HAVE_LIBAV
+ case CODEC_AAC:
+ cfg->handle.av.codec = __DECONST(AVCodec *,
+ avcodec_find_encoder_by_name("aac"));
+ if (cfg->handle.av.codec == NULL) {
+ DPRINTF("Codec AAC encoder not found\n");
+ goto av_error_0;
+ }
+ cfg->handle.av.format = avformat_alloc_context();
+ if (cfg->handle.av.format == NULL) {
+ DPRINTF("Could not allocate format context\n");
+ goto av_error_0;
+ }
+ cfg->handle.av.format->oformat =
+ av_guess_format("latm", NULL, NULL);
+ if (cfg->handle.av.format->oformat == NULL) {
+ DPRINTF("Could not guess output format\n");
+ goto av_error_1;
+ }
+ cfg->handle.av.stream = avformat_new_stream(
+ cfg->handle.av.format, cfg->handle.av.codec);
+
+ if (cfg->handle.av.stream == NULL) {
+ DPRINTF("Could not create new stream\n");
+ goto av_error_1;
+ }
+ cfg->handle.av.context = avcodec_alloc_context3(cfg->handle.av.codec);
+ if (cfg->handle.av.context == NULL) {
+ DPRINTF("Could not allocate audio context\n");
+ goto av_error_1;
+ }
+ /*avcodec_get_context_defaults3(cfg->handle.av.context,*/
+ /*cfg->handle.av.codec);*/
+
+ cfg->handle.av.context->bit_rate = 128000;
+ cfg->handle.av.context->sample_fmt = AV_SAMPLE_FMT_FLTP;
+ cfg->handle.av.context->sample_rate = samplerate;
+ switch (*pchannels) {
+ case 1:
+ cfg->handle.av.context->ch_layout = *(AVChannelLayout *)AV_CH_LAYOUT_MONO;
+ break;
+ default:
+ cfg->handle.av.context->ch_layout = *(AVChannelLayout *)AV_CH_LAYOUT_STEREO;
+ break;
+ }
+
+ cfg->handle.av.context->profile = FF_PROFILE_AAC_LOW;
+ if (1) {
+ AVDictionary *opts = NULL;
+
+ av_dict_set(&opts, "strict", "-2", 0);
+ av_dict_set_int(&opts, "latm", 1, 0);
+
+ if (avcodec_open2(cfg->handle.av.context,
+ cfg->handle.av.codec, &opts) < 0) {
+ av_dict_free(&opts);
+
+ DPRINTF("Could not open codec\n");
+ goto av_error_1;
+ }
+ av_dict_free(&opts);
+ }
+ cfg->handle.av.frame = av_frame_alloc();
+ if (cfg->handle.av.frame == NULL) {
+ DPRINTF("Could not allocate audio frame\n");
+ goto av_error_2;
+ }
+ cfg->handle.av.frame->nb_samples = cfg->handle.av.context->frame_size;
+ cfg->handle.av.frame->format = cfg->handle.av.context->sample_fmt;
+ cfg->handle.av.frame->ch_layout = cfg->handle.av.context->ch_layout;
+ cfg->rem_in_size = av_samples_get_buffer_size(NULL,
+ cfg->handle.av.context->ch_layout.nb_channels,
+ cfg->handle.av.context->frame_size,
+ cfg->handle.av.context->sample_fmt, 0);
+
+ cfg->rem_in_data = av_malloc(cfg->rem_in_size);
+ if (cfg->rem_in_data == NULL) {
+ DPRINTF("Could not allocate %u bytes sample buffer\n",
+ (unsigned)cfg->rem_in_size);
+ goto av_error_3;
+ }
+ retval = avcodec_fill_audio_frame(cfg->handle.av.frame,
+ cfg->handle.av.context->ch_layout.nb_channels,
+ cfg->handle.av.context->sample_fmt,
+ cfg->rem_in_data, cfg->rem_in_size, 0);
+ if (retval < 0) {
+ DPRINTF("Could not setup audio frame\n");
+ goto av_error_4;
+ }
+ break;
+av_error_4:
+ av_free(cfg->rem_in_data);
+av_error_3:
+ av_frame_free(&cfg->handle.av.frame);
+av_error_2:
+ avcodec_close(cfg->handle.av.context);
+av_error_1:
+ avformat_free_context(cfg->handle.av.format);
+ cfg->handle.av.context = NULL;
+av_error_0:
+ bt_close(pbe);
+ return (-1);
+#endif
+ default:
+ bt_close(pbe);
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+bt_rec_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ return (bt_receive(pbe->arg, ptr, len, 1));
+}
+
+static int
+bt_play_sbc_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ struct bt_config *cfg = pbe->arg;
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ int rem_size = 1;
+ int old_len = len;
+ int err = 0;
+
+ switch (cfg->blocks) {
+ case BLOCKS_4:
+ sbc->blocks = 4;
+ rem_size *= 4;
+ break;
+ case BLOCKS_8:
+ sbc->blocks = 8;
+ rem_size *= 8;
+ break;
+ case BLOCKS_12:
+ sbc->blocks = 12;
+ rem_size *= 12;
+ break;
+ default:
+ sbc->blocks = 16;
+ rem_size *= 16;
+ break;
+ }
+
+ switch (cfg->bands) {
+ case BANDS_4:
+ rem_size *= 4;
+ sbc->bands = 4;
+ break;
+ default:
+ rem_size *= 8;
+ sbc->bands = 8;
+ break;
+ }
+
+ /* store number of samples per frame */
+ sbc->framesamples = rem_size;
+
+ if (cfg->chmode != MODE_MONO) {
+ rem_size *= 2;
+ sbc->channels = 2;
+ } else {
+ sbc->channels = 1;
+ }
+
+ rem_size *= 2; /* 16-bit samples */
+
+ while (len > 0) {
+ int delta = len;
+
+ if (delta > (int)(rem_size - sbc->rem_len))
+ delta = (int)(rem_size - sbc->rem_len);
+
+ /* copy in samples */
+ memcpy((char *)sbc->music_data + sbc->rem_len, ptr, delta);
+
+ ptr = (char *)ptr + delta;
+ len -= delta;
+ sbc->rem_len += delta;
+
+ /* check if buffer is full */
+ if ((int)sbc->rem_len == rem_size) {
+ struct sbc_header *phdr = (struct sbc_header *)cfg->mtu_data;
+ uint32_t pkt_len;
+ uint32_t rem;
+
+ if (cfg->chmode == MODE_MONO)
+ sbc->channels = 1;
+ else
+ sbc->channels = 2;
+
+ pkt_len = sbc_encode_frame(cfg);
+
+ retry:
+ if (cfg->mtu_offset == 0) {
+ phdr->id = 0x80; /* RTP v2 */
+ phdr->id2 = 0x60; /* payload type 96. */
+ phdr->seqnumMSB = (uint8_t)(cfg->mtu_seqnumber >> 8);
+ phdr->seqnumLSB = (uint8_t)(cfg->mtu_seqnumber);
+ phdr->ts3 = (uint8_t)(cfg->mtu_timestamp >> 24);
+ phdr->ts2 = (uint8_t)(cfg->mtu_timestamp >> 16);
+ phdr->ts1 = (uint8_t)(cfg->mtu_timestamp >> 8);
+ phdr->ts0 = (uint8_t)(cfg->mtu_timestamp);
+ phdr->reserved0 = 0x01;
+ phdr->numFrames = 0;
+
+ cfg->mtu_seqnumber++;
+ cfg->mtu_offset += sizeof(*phdr);
+ }
+ /* compute bytes left */
+ rem = cfg->mtu - cfg->mtu_offset;
+
+ if (phdr->numFrames == 255 || rem < pkt_len) {
+ int xlen;
+
+ if (phdr->numFrames == 0)
+ return (-1);
+ do {
+ xlen = write(cfg->fd, cfg->mtu_data, cfg->mtu_offset);
+ } while (xlen < 0 && errno == EAGAIN);
+
+ if (xlen < 0)
+ return (-1);
+
+ cfg->mtu_offset = 0;
+ goto retry;
+ }
+ memcpy(cfg->mtu_data + cfg->mtu_offset, sbc->data, pkt_len);
+ memset(sbc->data, 0, pkt_len);
+ cfg->mtu_offset += pkt_len;
+ cfg->mtu_timestamp += sbc->framesamples;
+ phdr->numFrames++;
+
+ sbc->rem_len = 0;
+ }
+ }
+ if (err == 0)
+ return (old_len);
+ return (err);
+}
+
+#ifdef HAVE_LIBAV
+static int
+bt_play_aac_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ struct bt_config *cfg = pbe->arg;
+ struct aac_header {
+ uint8_t id;
+ uint8_t id2;
+ uint8_t seqnumMSB;
+ uint8_t seqnumLSB;
+ uint8_t ts3;
+ uint8_t ts2;
+ uint8_t ts1;
+ uint8_t ts0;
+ uint8_t sync3;
+ uint8_t sync2;
+ uint8_t sync1;
+ uint8_t sync0;
+ uint8_t fixed[8];
+ };
+ int old_len = len;
+ int err = 0;
+
+ while (len > 0) {
+ int delta = len;
+ int rem;
+
+ if (delta > (int)(cfg->rem_in_size - cfg->rem_in_len))
+ delta = (int)(cfg->rem_in_size - cfg->rem_in_len);
+
+ memcpy(cfg->rem_in_data + cfg->rem_in_len, ptr, delta);
+
+ ptr = (char *)ptr + delta;
+ len -= delta;
+ cfg->rem_in_len += delta;
+
+ /* check if buffer is full */
+ if (cfg->rem_in_len == cfg->rem_in_size) {
+ struct aac_header *phdr = (struct aac_header *)cfg->mtu_data;
+ AVPacket *pkt;
+ uint8_t *pkt_buf;
+ int pkt_len;
+
+ pkt = av_packet_alloc();
+ err = avcodec_send_frame(cfg->handle.av.context,
+ cfg->handle.av.frame);
+ if (err < 0) {
+ DPRINTF("Error encoding audio frame\n");
+ return (-1);
+ }
+ phdr->id = 0x80;/* RTP v2 */
+ phdr->id2 = 0x60; /* payload type 96. */
+ phdr->seqnumMSB = (uint8_t)(cfg->mtu_seqnumber >> 8);
+ phdr->seqnumLSB = (uint8_t)(cfg->mtu_seqnumber);
+ phdr->ts3 = (uint8_t)(cfg->mtu_timestamp >> 24);
+ phdr->ts2 = (uint8_t)(cfg->mtu_timestamp >> 16);
+ phdr->ts1 = (uint8_t)(cfg->mtu_timestamp >> 8);
+ phdr->ts0 = (uint8_t)(cfg->mtu_timestamp);
+ phdr->sync3 = 0;
+ phdr->sync2 = 0;
+ phdr->sync1 = 0;
+ phdr->sync0 = 0;
+ phdr->fixed[0] = 0xfc;
+ phdr->fixed[1] = 0x00;
+ phdr->fixed[2] = 0x00;
+ phdr->fixed[3] = 0xb0;
+ phdr->fixed[4] = 0x90;
+ phdr->fixed[5] = 0x80;
+ phdr->fixed[6] = 0x03;
+ phdr->fixed[7] = 0x00;
+
+ cfg->mtu_seqnumber++;
+ cfg->mtu_offset = sizeof(*phdr);
+
+ /* compute bytes left */
+ rem = cfg->mtu - cfg->mtu_offset;
+
+ if (avio_open_dyn_buf(&cfg->handle.av.format->pb) == 0) {
+ static int once = 0;
+
+ if (!once++)
+ (void)avformat_write_header(cfg->handle.av.format, NULL);
+ av_write_frame(cfg->handle.av.format, pkt);
+ av_packet_unref(pkt);
+ pkt_len = avio_close_dyn_buf(cfg->handle.av.format->pb, &pkt_buf);
+ if (rem < pkt_len)
+ DPRINTF("Out of buffer space\n");
+ if (pkt_len >= 3 && rem >= pkt_len) {
+ int xlen;
+
+ memcpy(cfg->mtu_data + cfg->mtu_offset, pkt_buf + 3, pkt_len - 3);
+
+ av_free(pkt_buf);
+
+ cfg->mtu_offset += pkt_len - 3;
+ if (cfg->chmode != MODE_MONO)
+ cfg->mtu_timestamp += cfg->rem_in_size / 4;
+ else
+ cfg->mtu_timestamp += cfg->rem_in_size / 2;
+ do {
+ xlen = write(cfg->fd, cfg->mtu_data, cfg->mtu_offset);
+ } while (xlen < 0 && errno == EAGAIN);
+
+ if (xlen < 0)
+ return (-1);
+ } else {
+ av_free(pkt_buf);
+ }
+ } else {
+ av_packet_unref(pkt);
+ }
+ /* reset remaining length */
+ cfg->rem_in_len = 0;
+ }
+ }
+ if (err == 0)
+ return (old_len);
+ return (err);
+}
+
+#endif
+
+static int
+bt_play_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ struct bt_config *cfg = pbe->arg;
+
+ switch (cfg->codec) {
+ case CODEC_SBC:
+ return (bt_play_sbc_transfer(pbe, ptr, len));
+#ifdef HAVE_LIBAV
+ case CODEC_AAC:
+ return (bt_play_aac_transfer(pbe, ptr, len));
+#endif
+ default:
+ return (-1);
+ }
+}
+
+static void
+bt_rec_delay(struct voss_backend *pbe __unused, int *pdelay)
+{
+ *pdelay = -1;
+}
+
+static void
+bt_play_delay(struct voss_backend *pbe __unused, int *pdelay)
+{
+ /* TODO */
+ *pdelay = -1;
+}
+
+struct voss_backend voss_backend_bt_rec = {
+ .open = bt_rec_open,
+ .close = bt_rec_close,
+ .transfer = bt_rec_transfer,
+ .delay = bt_rec_delay,
+ .arg = &bt_rec_cfg,
+};
+
+struct voss_backend voss_backend_bt_play = {
+ .open = bt_play_open,
+ .close = bt_play_close,
+ .transfer = bt_play_transfer,
+ .delay = bt_play_delay,
+ .arg = &bt_play_cfg,
+};
diff --git a/lib/virtual_oss/bt/bt.h b/lib/virtual_oss/bt/bt.h
new file mode 100644
index 000000000000..2abdb9eb021a
--- /dev/null
+++ b/lib/virtual_oss/bt/bt.h
@@ -0,0 +1,116 @@
+/*-
+ * Copyright (c) 2015 Hans Petter Selasky
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _BACKEND_BT_H_
+#define _BACKEND_BT_H_
+
+#ifdef HAVE_LIBAV
+#include <libavformat/avformat.h>
+#include <libavcodec/avcodec.h>
+#include <libavutil/opt.h>
+#endif
+
+#include "sbc_encode.h"
+
+struct bt_config {
+ uint8_t sep; /* SEID of the peer */
+ uint8_t media_Type;
+ uint8_t chmode;
+#define MODE_STEREO 2
+#define MODE_JOINT 3
+#define MODE_DUAL 1
+#define MODE_MONO 0
+ uint8_t allocm;
+#define ALLOC_LOUDNESS 0
+#define ALLOC_SNR 1
+ uint8_t bitpool;
+ uint8_t bands;
+#define BANDS_4 0
+#define BANDS_8 1
+ uint8_t blocks;
+#define BLOCKS_4 0
+#define BLOCKS_8 1
+#define BLOCKS_12 2
+#define BLOCKS_16 3
+ uint8_t freq;
+#define FREQ_UNDEFINED 255
+#define FREQ_16K 0
+#define FREQ_32K 1
+#define FREQ_44_1K 2
+#define FREQ_48K 3
+ uint16_t mtu;
+ uint8_t codec;
+#define CODEC_SBC 0x00
+#define CODEC_AAC 0x02
+ uint8_t aacMode1;
+ uint8_t aacMode2;
+
+ /* transcoding handle(s) */
+ union {
+#ifdef HAVE_LIBAV
+ struct {
+ AVCodec *codec;
+ AVCodecContext *context;
+ AVFormatContext *format;
+ AVFrame *frame;
+ AVStream *stream;
+ } av;
+#endif
+ struct sbc_encode *sbc_enc;
+ } handle;
+
+ /* audio input buffer */
+ uint32_t rem_in_len;
+ uint32_t rem_in_size;
+ uint8_t *rem_in_data;
+
+ /* data transport */
+ uint32_t mtu_seqnumber;
+ uint32_t mtu_timestamp;
+ uint32_t mtu_offset;
+
+ /* bluetooth file handles */
+ int fd;
+ int hc;
+
+ /* scratch buffer */
+ uint8_t mtu_data[65536];
+
+ /* acceptor state */
+ int8_t acceptor_state;
+#define acpInitial 1
+#define acpConfigurationSet 2
+#define acpStreamOpened 3
+#define acpStreamStarted 4
+#define acpStreamSuspended 5
+#define acpStreamClosed 6
+};
+
+size_t sbc_encode_frame(struct bt_config *);
+size_t sbc_decode_frame(struct bt_config *, int);
+
+int bt_receive(struct bt_config *cfg, void *ptr, int len, int use_delay);
+
+#endif /* _BACKEND_BT_H_ */
diff --git a/lib/virtual_oss/bt/cosdata-gen/Makefile b/lib/virtual_oss/bt/cosdata-gen/Makefile
new file mode 100644
index 000000000000..d08e263f32b5
--- /dev/null
+++ b/lib/virtual_oss/bt/cosdata-gen/Makefile
@@ -0,0 +1,12 @@
+# $NetBSD$
+
+WARNS?= 3
+
+PROG= cosdata
+SRCS= cosdata.c
+MAN=
+
+DPADD+= ${LIBMATH}
+LDADD+= -lm
+
+.include <bsd.prog.mk>
diff --git a/lib/virtual_oss/bt/cosdata-gen/cosdata.c b/lib/virtual_oss/bt/cosdata-gen/cosdata.c
new file mode 100644
index 000000000000..b8409cbd0216
--- /dev/null
+++ b/lib/virtual_oss/bt/cosdata-gen/cosdata.c
@@ -0,0 +1,177 @@
+/*-
+ * Copyright (c) 2015 - 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ * All rights reserved.
+ *
+ * This software is dedicated to the memory of -
+ * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
+ *
+ * Barry was a man who loved his music.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdint.h>
+
+static const double sbc8_coeffs[] = {
+ 0.00000000e+00, 1.56575398e-04, 3.43256425e-04, 5.54620202e-04,
+ 8.23919506e-04, 1.13992507e-03, 1.47640169e-03, 1.78371725e-03,
+ 2.01182542e-03, 2.10371989e-03, 1.99454554e-03, 1.61656283e-03,
+ 9.02154502e-04, -1.78805361e-04, -1.64973098e-03, -3.49717454e-03,
+ 5.65949473e-03, 8.02941163e-03, 1.04584443e-02, 1.27472335e-02,
+ 1.46525263e-02, 1.59045603e-02, 1.62208471e-02, 1.53184106e-02,
+ 1.29371806e-02, 8.85757540e-03, 2.92408442e-03, -4.91578024e-03,
+ -1.46404076e-02, -2.61098752e-02, -3.90751381e-02, -5.31873032e-02,
+ 6.79989431e-02, 8.29847578e-02, 9.75753918e-02, 1.11196689e-01,
+ 1.23264548e-01, 1.33264415e-01, 1.40753505e-01, 1.45389847e-01,
+ 1.46955068e-01, 1.45389847e-01, 1.40753505e-01, 1.33264415e-01,
+ 1.23264548e-01, 1.11196689e-01, 9.75753918e-02, 8.29847578e-02,
+ -6.79989431e-02, -5.31873032e-02, -3.90751381e-02, -2.61098752e-02,
+ -1.46404076e-02, -4.91578024e-03, 2.92408442e-03, 8.85757540e-03,
+ 1.29371806e-02, 1.53184106e-02, 1.62208471e-02, 1.59045603e-02,
+ 1.46525263e-02, 1.27472335e-02, 1.04584443e-02, 8.02941163e-03,
+ -5.65949473e-03, -3.49717454e-03, -1.64973098e-03, -1.78805361e-04,
+ 9.02154502e-04, 1.61656283e-03, 1.99454554e-03, 2.10371989e-03,
+ 2.01182542e-03, 1.78371725e-03, 1.47640169e-03, 1.13992507e-03,
+ 8.23919506e-04, 5.54620202e-04, 3.43256425e-04, 1.56575398e-04,
+};
+
+static const double sbc4_coeffs[] = {
+ 0.00000000e+00, 5.36548976e-04, 1.49188357e-03, 2.73370904e-03,
+ 3.83720193e-03, 3.89205149e-03, 1.86581691e-03, -3.06012286e-03,
+ 1.09137620e-02, 2.04385087e-02, 2.88757392e-02, 3.21939290e-02,
+ 2.58767811e-02, 6.13245186e-03, -2.88217274e-02, -7.76463494e-02,
+ 1.35593274e-01, 1.94987841e-01, 2.46636662e-01, 2.81828203e-01,
+ 2.94315332e-01, 2.81828203e-01, 2.46636662e-01, 1.94987841e-01,
+ -1.35593274e-01, -7.76463494e-02, -2.88217274e-02, 6.13245186e-03,
+ 2.58767811e-02, 3.21939290e-02, 2.88757392e-02, 2.04385087e-02,
+ -1.09137620e-02, -3.06012286e-03, 1.86581691e-03, 3.89205149e-03,
+ 3.83720193e-03, 2.73370904e-03, 1.49188357e-03, 5.36548976e-04,
+};
+
+#define AC(x) (int)(sizeof(x) / sizeof((x)[0]))
+
+int
+main(int argc, char **argv)
+{
+ float S[8][16];
+ int i;
+ int k;
+ int count = 0;
+
+ printf("/* sbc_coeffs.h - Automatically generated by cosdata.c. */\n"
+ "\n");
+
+ printf("static const float sbc_coeffs8[] = {\n ");
+ for (k = 0; k < AC(sbc8_coeffs); k++) {
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ printf("%0.12ff, ", (float)sbc8_coeffs[k]);
+ count++;
+ }
+ printf("\n};\n");
+
+ count = 0;
+ printf("static const float sbc_coeffs4[] = {\n ");
+ for (k = 0; k < AC(sbc4_coeffs); k++) {
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ printf("%0.12ff, ", (float)sbc4_coeffs[k]);
+ count++;
+ }
+ printf("\n};\n");
+
+ count = 0;
+ printf("static const float cosdata8[8][16] = {\n ");
+ for (i = 0; i < 8; i++) {
+ for (k = 0; k < 16; k++) {
+ S[i][k] = cosf((float)((i + 0.5) * (k - 4) * (M_PI / 8.0)));
+
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ if (k == 0)
+ printf("{ ");
+ printf("%0.12ff, ", S[i][k]);
+ if (k == 15)
+ printf("},");
+ count++;
+ }
+ }
+ printf("\n};\n");
+
+ count = 0;
+ printf("static const float cosdata4[4][8] = {\n ");
+ for (i = 0; i < 4; i++) {
+ for (k = 0; k < 8; k++) {
+ S[i][k] = cosf((float)((i + 0.5) * (k - 2) * (M_PI / 4.0)));
+
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ if (k == 0)
+ printf("{ ");
+ printf("%0.12ff, ", S[i][k]);
+ if (k == 7)
+ printf("},");
+ count++;
+ }
+ }
+ printf("\n};\n");
+
+ count = 0;
+ printf("static const float cosdecdata8[8][16] = {\n ");
+ for (i = 0; i < 8; i++) {
+ for (k = 0; k < 16; k++) {
+ S[i][k] = cosf((float)((i + 0.5) * (k + 4) * (M_PI / 8.0)));
+
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ if (k == 0)
+ printf("{ ");
+ printf("%0.12ff, ", S[i][k]);
+ if (k == 15)
+ printf("},");
+ count++;
+ }
+ }
+ printf("\n};\n");
+
+ count = 0;
+ printf("static const float cosdecdata4[4][8] = {\n ");
+ for (i = 0; i < 4; i++) {
+ for (k = 0; k < 8; k++) {
+ S[i][k] = cosf((float)((i + 0.5) * (k + 2) * (M_PI / 4.0)));
+
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ if (k == 0)
+ printf("{ ");
+ printf("%0.12ff, ", S[i][k]);
+ if (k == 7)
+ printf("},");
+ count++;
+ }
+ }
+ printf("\n};\n");
+
+ return (0);
+}
diff --git a/lib/virtual_oss/bt/sbc_coeffs.h b/lib/virtual_oss/bt/sbc_coeffs.h
new file mode 100644
index 000000000000..b9428033d50b
--- /dev/null
+++ b/lib/virtual_oss/bt/sbc_coeffs.h
@@ -0,0 +1,69 @@
+/* sbc_coeffs.h - Automatically generated by cosdata.c. */
+
+static const float sbc_coeffs8[] = {
+ 0.000000000000f, 0.000156575392f, 0.000343256426f, 0.000554620230f, 0.000823919487f, 0.001139925094f, 0.001476401696f, 0.001783717307f,
+ 0.002011825331f, 0.002103719860f, 0.001994545572f, 0.001616562833f, 0.000902154483f, -0.000178805363f, -0.001649730955f, -0.003497174475f,
+ 0.005659494549f, 0.008029411547f, 0.010458444245f, 0.012747233734f, 0.014652526006f, 0.015904560685f, 0.016220847145f, 0.015318410471f,
+ 0.012937180698f, 0.008857575245f, 0.002924084431f, -0.004915780388f, -0.014640407637f, -0.026109876111f, -0.039075139910f, -0.053187303245f,
+ 0.067998945713f, 0.082984760404f, 0.097575388849f, 0.111196689308f, 0.123264551163f, 0.133264422417f, 0.140753507614f, 0.145389840007f,
+ 0.146955072880f, 0.145389840007f, 0.140753507614f, 0.133264422417f, 0.123264551163f, 0.111196689308f, 0.097575388849f, 0.082984760404f,
+ -0.067998945713f, -0.053187303245f, -0.039075139910f, -0.026109876111f, -0.014640407637f, -0.004915780388f, 0.002924084431f, 0.008857575245f,
+ 0.012937180698f, 0.015318410471f, 0.016220847145f, 0.015904560685f, 0.014652526006f, 0.012747233734f, 0.010458444245f, 0.008029411547f,
+ -0.005659494549f, -0.003497174475f, -0.001649730955f, -0.000178805363f, 0.000902154483f, 0.001616562833f, 0.001994545572f, 0.002103719860f,
+ 0.002011825331f, 0.001783717307f, 0.001476401696f, 0.001139925094f, 0.000823919487f, 0.000554620230f, 0.000343256426f, 0.000156575392f,
+};
+static const float sbc_coeffs4[] = {
+ 0.000000000000f, 0.000536548963f, 0.001491883537f, 0.002733709058f, 0.003837201977f, 0.003892051522f, 0.001865816885f, -0.003060122952f,
+ 0.010913762264f, 0.020438509062f, 0.028875738382f, 0.032193928957f, 0.025876780972f, 0.006132451817f, -0.028821727261f, -0.077646352351f,
+ 0.135593280196f, 0.194987848401f, 0.246636658907f, 0.281828194857f, 0.294315338135f, 0.281828194857f, 0.246636658907f, 0.194987848401f,
+ -0.135593280196f, -0.077646352351f, -0.028821727261f, 0.006132451817f, 0.025876780972f, 0.032193928957f, 0.028875738382f, 0.020438509062f,
+ -0.010913762264f, -0.003060122952f, 0.001865816885f, 0.003892051522f, 0.003837201977f, 0.002733709058f, 0.001491883537f, 0.000536548963f,
+};
+static const float cosdata8[8][16] = {
+ { 0.707106769085f, 0.831469595432f, 0.923879504204f, 0.980785250664f, 1.000000000000f, 0.980785250664f, 0.923879504204f, 0.831469595432f,
+ 0.707106769085f, 0.555570244789f, 0.382683426142f, 0.195090353489f, -0.000000043711f, -0.195090323687f, -0.382683396339f, -0.555570185184f, },
+ { -0.707106769085f, -0.195090323687f, 0.382683426142f, 0.831469595432f, 1.000000000000f, 0.831469595432f, 0.382683426142f, -0.195090323687f,
+ -0.707106769085f, -0.980785310268f, -0.923879504204f, -0.555570423603f, 0.000000011925f, 0.555570065975f, 0.923879563808f, 0.980785310268f, },
+ { -0.707106828690f, -0.980785310268f, -0.382683396339f, 0.555570244789f, 1.000000000000f, 0.555570244789f, -0.382683396339f, -0.980785310268f,
+ -0.707106828690f, 0.195090413094f, 0.923879563808f, 0.831469655037f, 0.000000139071f, -0.831469774246f, -0.923879444599f, -0.195090219378f, },
+ { 0.707106649876f, -0.555570423603f, -0.923879504204f, 0.195090353489f, 1.000000000000f, 0.195090353489f, -0.923879504204f, -0.555570423603f,
+ 0.707106649876f, 0.831469655037f, -0.382683008909f, -0.980785369873f, -0.000000290067f, 0.980785250664f, 0.382683545351f, -0.831469595432f, },
+ { 0.707106769085f, 0.555570065975f, -0.923879504204f, -0.195090323687f, 1.000000000000f, -0.195090323687f, -0.923879504204f, 0.555570065975f,
+ 0.707106769085f, -0.831469774246f, -0.382683843374f, 0.980785250664f, -0.000000035775f, -0.980785250664f, 0.382683902979f, 0.831469714642f, },
+ { -0.707106590271f, 0.980785310268f, -0.382683575153f, -0.555570185184f, 1.000000000000f, -0.555570185184f, -0.382683575153f, 0.980785310268f,
+ -0.707106590271f, -0.195090219378f, 0.923879683018f, -0.831469595432f, -0.000000592058f, 0.831469714642f, -0.923879623413f, 0.195090919733f, },
+ { -0.707106530666f, 0.195090532303f, 0.382683604956f, -0.831469655037f, 1.000000000000f, -0.831469655037f, 0.382683604956f, 0.195090532303f,
+ -0.707106530666f, 0.980785310268f, -0.923879384995f, 0.555569529533f, -0.000000687457f, -0.555570006371f, 0.923879563808f, -0.980785191059f, },
+ { 0.707106828690f, -0.831469774246f, 0.923879563808f, -0.980785310268f, 1.000000000000f, -0.980785310268f, 0.923879563808f, -0.831469774246f,
+ 0.707106828690f, -0.555570065975f, 0.382683902979f, -0.195089668036f, 0.000000059624f, 0.195089548826f, -0.382683813572f, 0.555569946766f, },
+};
+static const float cosdata4[4][8] = {
+ { 0.707106769085f, 0.923879504204f, 1.000000000000f, 0.923879504204f, 0.707106769085f, 0.382683426142f, -0.000000043711f, -0.382683396339f, },
+ { -0.707106769085f, 0.382683426142f, 1.000000000000f, 0.382683426142f, -0.707106769085f, -0.923879504204f, 0.000000011925f, 0.923879563808f, },
+ { -0.707106828690f, -0.382683396339f, 1.000000000000f, -0.382683396339f, -0.707106828690f, 0.923879563808f, 0.000000139071f, -0.923879444599f, },
+ { 0.707106649876f, -0.923879504204f, 1.000000000000f, -0.923879504204f, 0.707106649876f, -0.382683008909f, -0.000000290067f, 0.382683545351f, },
+};
+static const float cosdecdata8[8][16] = {
+ { 0.707106769085f, 0.555570244789f, 0.382683426142f, 0.195090353489f, -0.000000043711f, -0.195090323687f, -0.382683396339f, -0.555570185184f,
+ -0.707106769085f, -0.831469655037f, -0.923879504204f, -0.980785310268f, -1.000000000000f, -0.980785310268f, -0.923879504204f, -0.831469535828f, },
+ { -0.707106769085f, -0.980785310268f, -0.923879504204f, -0.555570423603f, 0.000000011925f, 0.555570065975f, 0.923879563808f, 0.980785310268f,
+ 0.707106769085f, 0.195090532303f, -0.382683008909f, -0.831469774246f, -1.000000000000f, -0.831469714642f, -0.382683843374f, 0.195090577006f, },
+ { -0.707106828690f, 0.195090413094f, 0.923879563808f, 0.831469655037f, 0.000000139071f, -0.831469774246f, -0.923879444599f, -0.195090219378f,
+ 0.707106828690f, 0.980785310268f, 0.382683545351f, -0.555570065975f, -1.000000000000f, -0.555570542812f, 0.382683902979f, 0.980785191059f, },
+ { 0.707106649876f, 0.831469655037f, -0.382683008909f, -0.980785369873f, -0.000000290067f, 0.980785250664f, 0.382683545351f, -0.831469595432f,
+ -0.707107424736f, 0.555569529533f, 0.923879802227f, -0.195089668036f, -1.000000000000f, -0.195090815425f, 0.923879384995f, 0.555570483208f, },
+ { 0.707106769085f, -0.831469774246f, -0.382683843374f, 0.980785250664f, -0.000000035775f, -0.980785250664f, 0.382683902979f, 0.831469714642f,
+ -0.707106173038f, -0.555570006371f, 0.923879384995f, 0.195089548826f, -1.000000000000f, 0.195089697838f, 0.923879325390f, -0.555570125580f, },
+ { -0.707106590271f, -0.195090219378f, 0.923879683018f, -0.831469595432f, -0.000000592058f, 0.831469714642f, -0.923879623413f, 0.195090919733f,
+ 0.707107424736f, -0.980785191059f, 0.382683366537f, 0.555569946766f, -1.000000000000f, 0.555571198463f, 0.382683783770f, -0.980785667896f, },
+ { -0.707106530666f, 0.980785310268f, -0.923879384995f, 0.555569529533f, -0.000000687457f, -0.555570006371f, 0.923879563808f, -0.980785191059f,
+ 0.707106173038f, -0.195089071989f, -0.382684975863f, 0.831468641758f, -1.000000000000f, 0.831470131874f, -0.382683992386f, -0.195090129972f, },
+ { 0.707106828690f, -0.555570065975f, 0.382683902979f, -0.195089668036f, 0.000000059624f, 0.195089548826f, -0.382683813572f, 0.555569946766f,
+ -0.707106053829f, 0.831468641758f, -0.923880040646f, 0.980785369873f, -1.000000000000f, 0.980785429478f, -0.923880159855f, 0.831468760967f, },
+};
+static const float cosdecdata4[4][8] = {
+ { 0.707106769085f, 0.382683426142f, -0.000000043711f, -0.382683396339f, -0.707106769085f, -0.923879504204f, -1.000000000000f, -0.923879504204f, },
+ { -0.707106769085f, -0.923879504204f, 0.000000011925f, 0.923879563808f, 0.707106769085f, -0.382683008909f, -1.000000000000f, -0.382683843374f, },
+ { -0.707106828690f, 0.923879563808f, 0.000000139071f, -0.923879444599f, 0.707106828690f, 0.382683545351f, -1.000000000000f, 0.382683902979f, },
+ { 0.707106649876f, -0.382683008909f, -0.000000290067f, 0.382683545351f, -0.707107424736f, 0.923879802227f, -1.000000000000f, 0.923879384995f, },
+};
diff --git a/lib/virtual_oss/bt/sbc_encode.c b/lib/virtual_oss/bt/sbc_encode.c
new file mode 100644
index 000000000000..153f2e69e76e
--- /dev/null
+++ b/lib/virtual_oss/bt/sbc_encode.c
@@ -0,0 +1,701 @@
+/*-
+ * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ *
+ * This software is dedicated to the memory of -
+ * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
+ *
+ * Barry was a man who loved his music.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/uio.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "sbc_coeffs.h"
+#include "bt.h"
+
+#define SYNCWORD 0x9c
+#define ABS(x) (((x) < 0) ? -(x) : (x))
+#define BIT30 (1U << 30)
+#define BM(x) ((1LL << (x)) - 1LL)
+
+/* Loudness offset allocations. */
+static const int loudnessoffset8[4][8] = {
+ {-2, 0, 0, 0, 0, 0, 0, 1},
+ {-3, 0, 0, 0, 0, 0, 1, 2},
+ {-4, 0, 0, 0, 0, 0, 1, 2},
+ {-4, 0, 0, 0, 0, 0, 1, 2},
+};
+
+static const int loudnessoffset4[4][4] = {
+ {-1, 0, 0, 0},
+ {-2, 0, 0, 1},
+ {-2, 0, 0, 1},
+ {-2, 0, 0, 1},
+};
+
+static uint8_t
+calc_scalefactors_joint(struct sbc_encode *sbc)
+{
+ float sb_j[16][2];
+ uint32_t x;
+ uint32_t y;
+ uint8_t block;
+ uint8_t joint;
+ uint8_t sb;
+ uint8_t lz;
+
+ joint = 0;
+ for (sb = 0; sb != sbc->bands - 1; sb++) {
+ for (block = 0; block < sbc->blocks; block++) {
+ sb_j[block][0] = (sbc->samples[block][0][sb] +
+ sbc->samples[block][1][sb]) / 2.0f;
+ sb_j[block][1] = (sbc->samples[block][0][sb] -
+ sbc->samples[block][1][sb]) / 2.0f;
+ }
+
+ x = 1 << 15;
+ y = 1 << 15;
+ for (block = 0; block < sbc->blocks; block++) {
+ x |= (uint32_t)ABS(sb_j[block][0]);
+ y |= (uint32_t)ABS(sb_j[block][1]);
+ }
+
+ lz = 1;
+ while (!(x & BIT30)) {
+ lz++;
+ x <<= 1;
+ }
+ x = 16 - lz;
+
+ lz = 1;
+ while (!(y & BIT30)) {
+ lz++;
+ y <<= 1;
+ }
+ y = 16 - lz;
+
+ if ((sbc->scalefactor[0][sb] + sbc->scalefactor[1][sb]) > x + y) {
+ joint |= 1 << (sbc->bands - sb - 1);
+ sbc->scalefactor[0][sb] = x;
+ sbc->scalefactor[1][sb] = y;
+ for (block = 0; block < sbc->blocks; block++) {
+ sbc->samples[block][0][sb] = sb_j[block][0];
+ sbc->samples[block][1][sb] = sb_j[block][1];
+ }
+ }
+ }
+ return (joint);
+}
+
+static void
+calc_scalefactors(struct sbc_encode *sbc)
+{
+ uint8_t block;
+ uint8_t ch;
+ uint8_t sb;
+
+ for (ch = 0; ch != sbc->channels; ch++) {
+ for (sb = 0; sb != sbc->bands; sb++) {
+ uint32_t x = 1 << 15;
+ uint8_t lx = 1;
+
+ for (block = 0; block != sbc->blocks; block++)
+ x |= (uint32_t)ABS(sbc->samples[block][ch][sb]);
+
+ while (!(x & BIT30)) {
+ lx++;
+ x <<= 1;
+ }
+ sbc->scalefactor[ch][sb] = 16 - lx;
+ }
+ }
+}
+
+static void
+calc_bitneed(struct bt_config *cfg)
+{
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ int32_t bitneed[2][8];
+ int32_t max_bitneed, bitcount;
+ int32_t slicecount, bitslice;
+ int32_t loudness;
+ int ch, sb, start_chan = 0;
+
+ if (cfg->chmode == MODE_DUAL)
+ sbc->channels = 1;
+
+next_chan:
+ max_bitneed = 0;
+ bitcount = 0;
+ slicecount = 0;
+
+ if (cfg->allocm == ALLOC_SNR) {
+ for (ch = start_chan; ch < sbc->channels; ch++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ bitneed[ch][sb] = sbc->scalefactor[ch][sb];
+
+ if (bitneed[ch][sb] > max_bitneed)
+ max_bitneed = bitneed[ch][sb];
+ }
+ }
+ } else {
+ for (ch = start_chan; ch < sbc->channels; ch++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->scalefactor[ch][sb] == 0) {
+ bitneed[ch][sb] = -5;
+ } else {
+ if (sbc->bands == 8) {
+ loudness = sbc->scalefactor[ch][sb] -
+ loudnessoffset8[cfg->freq][sb];
+ } else {
+ loudness = sbc->scalefactor[ch][sb] -
+ loudnessoffset4[cfg->freq][sb];
+ }
+ if (loudness > 0)
+ bitneed[ch][sb] = loudness / 2;
+ else
+ bitneed[ch][sb] = loudness;
+ }
+ if (bitneed[ch][sb] > max_bitneed)
+ max_bitneed = bitneed[ch][sb];
+ }
+ }
+ }
+
+ slicecount = bitcount = 0;
+ bitslice = max_bitneed + 1;
+ do {
+ bitslice--;
+ bitcount += slicecount;
+ slicecount = 0;
+ for (ch = start_chan; ch < sbc->channels; ch++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if ((bitneed[ch][sb] > bitslice + 1) &&
+ (bitneed[ch][sb] < bitslice + 16))
+ slicecount++;
+ else if (bitneed[ch][sb] == bitslice + 1)
+ slicecount += 2;
+ }
+ }
+ } while (bitcount + slicecount < cfg->bitpool);
+
+ /* check if exactly one more fits */
+ if (bitcount + slicecount == cfg->bitpool) {
+ bitcount += slicecount;
+ bitslice--;
+ }
+ for (ch = start_chan; ch < sbc->channels; ch++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (bitneed[ch][sb] < bitslice + 2) {
+ sbc->bits[ch][sb] = 0;
+ } else {
+ sbc->bits[ch][sb] = bitneed[ch][sb] - bitslice;
+ if (sbc->bits[ch][sb] > 16)
+ sbc->bits[ch][sb] = 16;
+ }
+ }
+ }
+
+ if (cfg->chmode == MODE_DUAL)
+ ch = start_chan;
+ else
+ ch = 0;
+ sb = 0;
+ while (bitcount < cfg->bitpool && sb < sbc->bands) {
+ if ((sbc->bits[ch][sb] >= 2) && (sbc->bits[ch][sb] < 16)) {
+ sbc->bits[ch][sb]++;
+ bitcount++;
+ } else if ((bitneed[ch][sb] == bitslice + 1) &&
+ (cfg->bitpool > bitcount + 1)) {
+ sbc->bits[ch][sb] = 2;
+ bitcount += 2;
+ }
+ if (sbc->channels == 1 || start_chan == 1)
+ sb++;
+ else if (ch == 1) {
+ ch = 0;
+ sb++;
+ } else
+ ch = 1;
+ }
+
+ if (cfg->chmode == MODE_DUAL)
+ ch = start_chan;
+ else
+ ch = 0;
+ sb = 0;
+ while (bitcount < cfg->bitpool && sb < sbc->bands) {
+ if (sbc->bits[ch][sb] < 16) {
+ sbc->bits[ch][sb]++;
+ bitcount++;
+ }
+ if (sbc->channels == 1 || start_chan == 1)
+ sb++;
+ else if (ch == 1) {
+ ch = 0;
+ sb++;
+ } else
+ ch = 1;
+ }
+
+ if (cfg->chmode == MODE_DUAL && start_chan == 0) {
+ start_chan = 1;
+ sbc->channels = 2;
+ goto next_chan;
+ }
+}
+
+static void
+sbc_store_bits_crc(struct sbc_encode *sbc, uint32_t numbits, uint32_t value)
+{
+ uint32_t off = sbc->bitoffset;
+
+ while (numbits-- && off != sbc->maxoffset) {
+ if (value & (1 << numbits)) {
+ sbc->data[off / 8] |= 1 << ((7 - off) & 7);
+ sbc->crc ^= 0x80;
+ }
+ sbc->crc *= 2;
+ if (sbc->crc & 0x100)
+ sbc->crc ^= 0x11d; /* CRC-8 polynomial */
+
+ off++;
+ }
+ sbc->bitoffset = off;
+}
+
+static int
+sbc_encode(struct bt_config *cfg)
+{
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ const int16_t *input = sbc->music_data;
+ float delta[2][8];
+ float levels[2][8];
+ float mask[2][8];
+ float S;
+ float *X;
+ float Z[80];
+ float Y[80];
+ float audioout;
+ int16_t left[8];
+ int16_t right[8];
+ int16_t *data;
+ int numsamples;
+ int i;
+ int k;
+ int block;
+ int chan;
+ int sb;
+
+ for (block = 0; block < sbc->blocks; block++) {
+
+ for (i = 0; i < sbc->bands; i++) {
+ left[i] = *input++;
+ if (sbc->channels == 2)
+ right[i] = *input++;
+ }
+
+ for (chan = 0; chan < sbc->channels; chan++) {
+
+ /* select right or left channel */
+ if (chan == 0) {
+ X = sbc->left;
+ data = left;
+ } else {
+ X = sbc->right;
+ data = right;
+ }
+
+ /* shift up old data */
+ for (i = (sbc->bands * 10) - 1; i > sbc->bands - 1; i--)
+ X[i] = X[i - sbc->bands];
+ k = 0;
+ for (i = sbc->bands - 1; i >= 0; i--)
+ X[i] = data[k++];
+ for (i = 0; i < sbc->bands * 10; i++) {
+ if (sbc->bands == 8)
+ Z[i] = sbc_coeffs8[i] * X[i];
+ else
+ Z[i] = sbc_coeffs4[i] * X[i];
+ }
+ for (i = 0; i < sbc->bands * 2; i++) {
+ Y[i] = 0;
+ for (k = 0; k < 5; k++)
+ Y[i] += Z[i + k * sbc->bands * 2];
+ }
+ for (i = 0; i < sbc->bands; i++) {
+ S = 0;
+ for (k = 0; k < sbc->bands * 2; k++) {
+ if (sbc->bands == 8) {
+ S += cosdata8[i][k] * Y[k];
+ } else {
+ S += cosdata4[i][k] * Y[k];
+ }
+ }
+ sbc->samples[block][chan][i] = S * (1 << 15);
+ }
+ }
+ }
+
+ calc_scalefactors(sbc);
+
+ if (cfg->chmode == MODE_JOINT)
+ sbc->join = calc_scalefactors_joint(sbc);
+ else
+ sbc->join = 0;
+
+ calc_bitneed(cfg);
+
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->bits[chan][sb] == 0)
+ continue;
+ mask[chan][sb] = BM(sbc->bits[chan][sb]);
+ levels[chan][sb] = mask[chan][sb] *
+ (1LL << (15 - sbc->scalefactor[chan][sb]));
+ delta[chan][sb] =
+ (1LL << (sbc->scalefactor[chan][sb] + 16));
+ }
+ }
+
+ numsamples = 0;
+ for (block = 0; block < sbc->blocks; block++) {
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->bits[chan][sb] == 0)
+ continue;
+ audioout = (levels[chan][sb] *
+ (delta[chan][sb] + sbc->samples[block][chan][sb]));
+ audioout /= (1LL << 32);
+
+ audioout = roundf(audioout);
+
+ /* range check */
+ if (audioout > mask[chan][sb])
+ audioout = mask[chan][sb];
+
+ sbc->output[numsamples++] = audioout;
+ }
+ }
+ }
+ return (numsamples);
+}
+
+static void
+sbc_decode(struct bt_config *cfg)
+{
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ float delta[2][8];
+ float levels[2][8];
+ float audioout;
+ float *X;
+ float *V;
+ float left[160];
+ float right[160];
+ float U[160];
+ float W[160];
+ float S[8];
+ int position;
+ int block;
+ int chan;
+ int sb;
+ int i;
+ int k;
+
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ levels[chan][sb] = (1 << sbc->bits[chan][sb]) - 1;
+ delta[chan][sb] = (1 << sbc->scalefactor[chan][sb]);
+ }
+ }
+
+ i = 0;
+ for (block = 0; block < sbc->blocks; block++) {
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->bits[chan][sb] == 0) {
+ audioout = 0;
+ } else {
+ audioout =
+ ((((sbc->output[i] * 2.0f) + 1.0f) * delta[chan][sb]) /
+ levels[chan][sb]) - delta[chan][sb];
+ }
+ sbc->output[i++] = audioout;
+ }
+ }
+ }
+
+ if (cfg->chmode == MODE_JOINT) {
+ i = 0;
+ while (i < (sbc->blocks * sbc->bands * sbc->channels)) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->join & (1 << (sbc->bands - sb - 1))) {
+ audioout = sbc->output[i];
+ sbc->output[i] = (2.0f * sbc->output[i]) +
+ (2.0f * sbc->output[i + sbc->bands]);
+ sbc->output[i + sbc->bands] =
+ (2.0f * audioout) -
+ (2.0f * sbc->output[i + sbc->bands]);
+ sbc->output[i] /= 2.0f;
+ sbc->output[i + sbc->bands] /= 2.0f;
+ }
+ i++;
+ }
+ i += sbc->bands;
+ }
+ }
+ position = 0;
+ for (block = 0; block < sbc->blocks; block++) {
+ for (chan = 0; chan < sbc->channels; chan++) {
+ /* select right or left channel */
+ if (chan == 0) {
+ X = left;
+ V = sbc->left;
+ } else {
+ X = right;
+ V = sbc->right;
+ }
+ for (i = 0; i < sbc->bands; i++)
+ S[i] = sbc->output[position++];
+
+ for (i = (sbc->bands * 20) - 1; i >= (sbc->bands * 2); i--)
+ V[i] = V[i - (sbc->bands * 2)];
+ for (k = 0; k < sbc->bands * 2; k++) {
+ float vk = 0;
+ for (i = 0; i < sbc->bands; i++) {
+ if (sbc->bands == 8) {
+ vk += cosdecdata8[i][k] * S[i];
+ } else {
+ vk += cosdecdata4[i][k] * S[i];
+ }
+ }
+ V[k] = vk;
+ }
+ for (i = 0; i <= 4; i++) {
+ for (k = 0; k < sbc->bands; k++) {
+ U[(i * sbc->bands * 2) + k] =
+ V[(i * sbc->bands * 4) + k];
+ U[(i * sbc->bands
+ * 2) + sbc->bands + k] =
+ V[(i * sbc->bands * 4) +
+ (sbc->bands * 3) + k];
+ }
+ }
+ for (i = 0; i < sbc->bands * 10; i++) {
+ if (sbc->bands == 4) {
+ W[i] = U[i] * (sbc_coeffs4[i] * -4.0f);
+ } else if (sbc->bands == 8) {
+ W[i] = U[i] * (sbc_coeffs8[i] * -8.0f);
+ } else {
+ W[i] = 0;
+ }
+ }
+
+ for (k = 0; k < sbc->bands; k++) {
+ unsigned int offset = k + (block * sbc->bands);
+
+ X[offset] = 0;
+ for (i = 0; i < 10; i++) {
+ X[offset] += W[k + (i * sbc->bands)];
+ }
+
+ if (X[offset] > 32767.0)
+ X[offset] = 32767.0;
+ else if (X[offset] < -32767.0)
+ X[offset] = -32767.0;
+ }
+ }
+ }
+
+ for (i = 0, k = 0; k != (sbc->blocks * sbc->bands); k++) {
+ sbc->music_data[i++] = left[k];
+ if (sbc->channels == 2)
+ sbc->music_data[i++] = right[k];
+ }
+}
+
+size_t
+sbc_encode_frame(struct bt_config *cfg)
+{
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ uint8_t config;
+ uint8_t block;
+ uint8_t chan;
+ uint8_t sb;
+ uint8_t j;
+ uint8_t i;
+
+ config = (cfg->freq << 6) | (cfg->blocks << 4) |
+ (cfg->chmode << 2) | (cfg->allocm << 1) | cfg->bands;
+
+ sbc_encode(cfg);
+
+ /* set initial CRC */
+ sbc->crc = 0x5e;
+
+ /* reset data position and size */
+ sbc->bitoffset = 0;
+ sbc->maxoffset = sizeof(sbc->data) * 8;
+
+ sbc_store_bits_crc(sbc, 8, SYNCWORD);
+ sbc_store_bits_crc(sbc, 8, config);
+ sbc_store_bits_crc(sbc, 8, cfg->bitpool);
+
+ /* skip 8-bit CRC */
+ sbc->bitoffset += 8;
+
+ if (cfg->chmode == MODE_JOINT) {
+ if (sbc->bands == 8)
+ sbc_store_bits_crc(sbc, 8, sbc->join);
+ else if (sbc->bands == 4)
+ sbc_store_bits_crc(sbc, 4, sbc->join);
+ }
+ for (i = 0; i < sbc->channels; i++) {
+ for (j = 0; j < sbc->bands; j++)
+ sbc_store_bits_crc(sbc, 4, sbc->scalefactor[i][j]);
+ }
+
+ /* store 8-bit CRC */
+ sbc->data[3] = (sbc->crc & 0xFF);
+
+ i = 0;
+ for (block = 0; block < sbc->blocks; block++) {
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->bits[chan][sb] == 0)
+ continue;
+
+ sbc_store_bits_crc(sbc, sbc->bits[chan][sb], sbc->output[i++]);
+ }
+ }
+ }
+ return ((sbc->bitoffset + 7) / 8);
+}
+
+static uint32_t
+sbc_load_bits_crc(struct sbc_encode *sbc, uint32_t numbits)
+{
+ uint32_t off = sbc->bitoffset;
+ uint32_t value = 0;
+
+ while (numbits-- && off != sbc->maxoffset) {
+ if (sbc->rem_data_ptr[off / 8] & (1 << ((7 - off) & 7))) {
+ value |= (1 << numbits);
+ sbc->crc ^= 0x80;
+ }
+ sbc->crc *= 2;
+ if (sbc->crc & 0x100)
+ sbc->crc ^= 0x11d; /* CRC-8 polynomial */
+
+ off++;
+ }
+ sbc->bitoffset = off;
+ return (value);
+}
+
+size_t
+sbc_decode_frame(struct bt_config *cfg, int bits)
+{
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ uint8_t config;
+ uint8_t block;
+ uint8_t chan;
+ uint8_t sb;
+ uint8_t j;
+ uint8_t i;
+
+ sbc->rem_off = 0;
+ sbc->rem_len = 0;
+
+ config = (cfg->freq << 6) | (cfg->blocks << 4) |
+ (cfg->chmode << 2) | (cfg->allocm << 1) | cfg->bands;
+
+ /* set initial CRC */
+ sbc->crc = 0x5e;
+
+ /* reset data position and size */
+ sbc->bitoffset = 0;
+ sbc->maxoffset = bits;
+
+ /* verify SBC header */
+ if (sbc->maxoffset < (8 * 4))
+ return (0);
+ if (sbc_load_bits_crc(sbc, 8) != SYNCWORD)
+ return (0);
+ if (sbc_load_bits_crc(sbc, 8) != config)
+ return (0);
+ cfg->bitpool = sbc_load_bits_crc(sbc, 8);
+
+ (void)sbc_load_bits_crc(sbc, 8);/* CRC */
+
+ if (cfg->chmode == MODE_JOINT) {
+ if (sbc->bands == 8)
+ sbc->join = sbc_load_bits_crc(sbc, 8);
+ else if (sbc->bands == 4)
+ sbc->join = sbc_load_bits_crc(sbc, 4);
+ else
+ sbc->join = 0;
+ } else {
+ sbc->join = 0;
+ }
+
+ for (i = 0; i < sbc->channels; i++) {
+ for (j = 0; j < sbc->bands; j++)
+ sbc->scalefactor[i][j] = sbc_load_bits_crc(sbc, 4);
+ }
+
+ calc_bitneed(cfg);
+
+ i = 0;
+ for (block = 0; block < sbc->blocks; block++) {
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->bits[chan][sb] == 0) {
+ i++;
+ continue;
+ }
+ sbc->output[i++] =
+ sbc_load_bits_crc(sbc, sbc->bits[chan][sb]);
+ }
+ }
+ }
+
+ sbc_decode(cfg);
+
+ sbc->rem_off = 0;
+ sbc->rem_len = sbc->blocks * sbc->channels * sbc->bands;
+
+ return ((sbc->bitoffset + 7) / 8);
+}
diff --git a/lib/virtual_oss/bt/sbc_encode.h b/lib/virtual_oss/bt/sbc_encode.h
new file mode 100644
index 000000000000..71f8460a242e
--- /dev/null
+++ b/lib/virtual_oss/bt/sbc_encode.h
@@ -0,0 +1,82 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ *
+ * This software is dedicated to the memory of -
+ * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
+ *
+ * Barry was a man who loved his music.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SBC_ENCODE_H_
+#define _SBC_ENCODE_H_
+
+#define MIN_BITPOOL 2
+#define DEFAULT_MAXBPOOL 250
+
+/*
+ * SBC header format
+ */
+struct sbc_header {
+ uint8_t id;
+ uint8_t id2;
+ uint8_t seqnumMSB;
+ uint8_t seqnumLSB;
+ uint8_t ts3;
+ uint8_t ts2;
+ uint8_t ts1;
+ uint8_t ts0;
+ uint8_t reserved3;
+ uint8_t reserved2;
+ uint8_t reserved1;
+ uint8_t reserved0;
+ uint8_t numFrames;
+};
+
+struct sbc_encode {
+ int16_t music_data[256];
+ uint8_t data[1024];
+ uint8_t *rem_data_ptr;
+ int rem_data_len;
+ int rem_data_frames;
+ int bits[2][8];
+ float output[256];
+ float left[160];
+ float right[160];
+ float samples[16][2][8];
+ uint32_t rem_len;
+ uint32_t rem_off;
+ uint32_t bitoffset;
+ uint32_t maxoffset;
+ uint32_t crc;
+ uint16_t framesamples;
+ uint8_t scalefactor[2][8];
+ uint8_t channels;
+ uint8_t bands;
+ uint8_t blocks;
+ uint8_t join;
+};
+
+#endif /* _SBC_ENCODE_H_ */
diff --git a/lib/virtual_oss/null/Makefile b/lib/virtual_oss/null/Makefile
new file mode 100644
index 000000000000..ec5c2d40f665
--- /dev/null
+++ b/lib/virtual_oss/null/Makefile
@@ -0,0 +1,10 @@
+SHLIB_NAME= voss_null.so
+SHLIBDIR= ${LIBDIR}/virtual_oss
+
+SRCS= null.c
+
+CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \
+ -I${SRCTOP}/contrib/libsamplerate
+LIBADD= samplerate
+
+.include <bsd.lib.mk>
diff --git a/lib/virtual_oss/null/null.c b/lib/virtual_oss/null/null.c
new file mode 100644
index 000000000000..149c6e3e8c6a
--- /dev/null
+++ b/lib/virtual_oss/null/null.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 2015-2022 Hans Petter Selasky
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/filio.h>
+#include <sys/soundcard.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <time.h>
+
+#include "backend.h"
+#include "int.h"
+
+static void
+null_close(struct voss_backend *pbe __unused)
+{
+}
+
+static int
+null_open(struct voss_backend *pbe __unused, const char *devname __unused,
+ int samplerate __unused, int bufsize __unused, int *pchannels __unused,
+ int *pformat)
+{
+ int value[3];
+ int i;
+
+ value[0] = *pformat & VPREFERRED_SNE_AFMT;
+ value[1] = *pformat & VPREFERRED_SLE_AFMT;
+ value[2] = *pformat & VPREFERRED_SBE_AFMT;
+
+ for (i = 0; i != 3; i++) {
+ if (value[i] == 0)
+ continue;
+ *pformat = value[i];
+ return (0);
+ }
+ return (-1);
+}
+
+static int
+null_rec_transfer(struct voss_backend *pbe __unused, void *ptr, int len)
+{
+
+ if (voss_has_synchronization == 0)
+ virtual_oss_wait();
+ memset(ptr, 0, len);
+ return (len);
+}
+
+static int
+null_play_transfer(struct voss_backend *pbe __unused, void *ptr __unused,
+ int len)
+{
+ return (len);
+}
+
+static void
+null_delay(struct voss_backend *pbe __unused, int *pdelay)
+{
+ *pdelay = -1;
+}
+
+struct voss_backend voss_backend_null_rec = {
+ .open = null_open,
+ .close = null_close,
+ .transfer = null_rec_transfer,
+ .delay = null_delay,
+};
+
+struct voss_backend voss_backend_null_play = {
+ .open = null_open,
+ .close = null_close,
+ .transfer = null_play_transfer,
+ .delay = null_delay,
+};
diff --git a/lib/virtual_oss/oss/Makefile b/lib/virtual_oss/oss/Makefile
new file mode 100644
index 000000000000..257d7f0c0bae
--- /dev/null
+++ b/lib/virtual_oss/oss/Makefile
@@ -0,0 +1,10 @@
+SHLIB_NAME= voss_oss.so
+SHLIBDIR= ${LIBDIR}/virtual_oss
+
+SRCS= oss.c
+
+CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \
+ -I${SRCTOP}/contrib/libsamplerate
+LIBADD= samplerate
+
+.include <bsd.lib.mk>
diff --git a/lib/virtual_oss/oss/oss.c b/lib/virtual_oss/oss/oss.c
new file mode 100644
index 000000000000..b4779f9108d9
--- /dev/null
+++ b/lib/virtual_oss/oss/oss.c
@@ -0,0 +1,197 @@
+/*-
+ * Copyright (c) 2015-2019 Hans Petter Selasky
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/filio.h>
+#include <sys/soundcard.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <poll.h>
+
+#include "backend.h"
+#include "int.h"
+
+static int
+oss_set_format(int fd, int *format)
+{
+ int value[6];
+ int error;
+ int fmt;
+ int i;
+
+ value[0] = *format & VPREFERRED_SNE_AFMT;
+ value[1] = *format & VPREFERRED_UNE_AFMT;
+ value[2] = *format & VPREFERRED_SLE_AFMT;
+ value[3] = *format & VPREFERRED_SBE_AFMT;
+ value[4] = *format & VPREFERRED_ULE_AFMT;
+ value[5] = *format & VPREFERRED_UBE_AFMT;
+
+ for (i = 0; i != 6; i++) {
+ fmt = value[i];
+ if (fmt == 0)
+ continue;
+ error = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
+ /* make sure we got the format we asked for */
+ if (error == 0 && fmt == value[i]) {
+ *format = fmt;
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+static void
+oss_close(struct voss_backend *pbe)
+{
+ if (pbe->fd > -1) {
+ close(pbe->fd);
+ pbe->fd = -1;
+ }
+}
+
+static int
+oss_open(struct voss_backend *pbe, const char *devname, int samplerate,
+ int bufsize, int *pchannels, int *pformat, int attr, int fionbio)
+{
+ int temp;
+ int err;
+
+ pbe->fd = open(devname, attr);
+ if (pbe->fd < 0) {
+ warn("Could not open DSP device '%s'", devname);
+ return (-1);
+ }
+ err = ioctl(pbe->fd, FIONBIO, &fionbio);
+ if (err < 0) {
+ warn("Could not set blocking mode on DSP");
+ goto error;
+ }
+ err = oss_set_format(pbe->fd, pformat);
+ if (err < 0) {
+ warn("Could not set sample format 0x%08x", *pformat);
+ goto error;
+ }
+ temp = *pchannels;
+ bufsize /= temp; /* get buffer size per channel */
+ do {
+ err = ioctl(pbe->fd, SOUND_PCM_WRITE_CHANNELS, &temp);
+ } while (err < 0 && --temp > 0);
+
+ err = ioctl(pbe->fd, SOUND_PCM_READ_CHANNELS, &temp);
+ if (err < 0 || temp <= 0 || temp > *pchannels) {
+ warn("Could not set DSP channels: %d / %d", temp, *pchannels);
+ goto error;
+ }
+ *pchannels = temp;
+
+ temp = samplerate;
+ err = ioctl(pbe->fd, SNDCTL_DSP_SPEED, &temp);
+ if (err < 0 || temp != samplerate) {
+ warn("Could not set sample rate to %d / %d Hz", temp, samplerate);
+ goto error;
+ }
+
+ temp = bufsize * (*pchannels);
+ err = ioctl(pbe->fd, SNDCTL_DSP_SETBLKSIZE, &temp);
+ if (err < 0) {
+ warn("Could not set block size to %d", temp);
+ goto error;
+ }
+ return (0);
+error:
+ close(pbe->fd);
+ pbe->fd = -1;
+ return (-1);
+}
+
+static int
+oss_rec_open(struct voss_backend *pbe, const char *devname, int samplerate,
+ int bufsize, int *pchannels, int *pformat)
+{
+ return (oss_open(pbe, devname, samplerate, bufsize, pchannels, pformat, O_RDONLY, 0));
+}
+
+static int
+oss_play_open(struct voss_backend *pbe, const char *devname, int samplerate,
+ int bufsize, int *pchannels, int *pformat)
+{
+ bufsize *= 4; /* XXX allow extra space for jitter */
+ return (oss_open(pbe, devname, samplerate, bufsize, pchannels, pformat, O_WRONLY, 0));
+}
+
+static int
+oss_rec_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ struct pollfd fds = { .fd = pbe->fd, .events = POLLIN | POLLRDNORM };
+ int err;
+
+ /* wait at maximum 2 seconds for data, else something is wrong */
+ err = poll(&fds, 1, 2000);
+ if (err < 1)
+ return (-1);
+ return (read(pbe->fd, ptr, len));
+}
+
+static int
+oss_play_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ return (write(pbe->fd, ptr, len));
+}
+
+static void
+oss_rec_delay(struct voss_backend *pbe, int *pdelay)
+{
+ if (ioctl(pbe->fd, FIONREAD, pdelay) != 0)
+ *pdelay = -1;
+}
+
+static void
+oss_play_delay(struct voss_backend *pbe, int *pdelay)
+{
+ if (voss_has_synchronization != 0 ||
+ ioctl(pbe->fd, SNDCTL_DSP_GETODELAY, pdelay) != 0)
+ *pdelay = -1;
+}
+
+struct voss_backend voss_backend_oss_rec = {
+ .open = oss_rec_open,
+ .close = oss_close,
+ .transfer = oss_rec_transfer,
+ .delay = oss_rec_delay,
+ .fd = -1,
+};
+
+struct voss_backend voss_backend_oss_play = {
+ .open = oss_play_open,
+ .close = oss_close,
+ .transfer = oss_play_transfer,
+ .delay = oss_play_delay,
+ .fd = -1,
+};
diff --git a/lib/virtual_oss/sndio/Makefile b/lib/virtual_oss/sndio/Makefile
new file mode 100644
index 000000000000..9b5af63a3246
--- /dev/null
+++ b/lib/virtual_oss/sndio/Makefile
@@ -0,0 +1,12 @@
+SHLIB_NAME= voss_sndio.so
+SHLIBDIR= ${LIBDIR}/virtual_oss
+
+SRCS= sndio.c
+
+CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \
+ -I${SRCTOP}/contrib/libsamplerate \
+ -I${LOCALBASE:U/usr/local}/include
+LDFLAGS+= -L${LOCALBASE:U/usr/local}/lib -lsndio
+LIBADD= samplerate
+
+.include <bsd.lib.mk>
diff --git a/lib/virtual_oss/sndio/sndio.c b/lib/virtual_oss/sndio/sndio.c
new file mode 100644
index 000000000000..2d1a3411049b
--- /dev/null
+++ b/lib/virtual_oss/sndio/sndio.c
@@ -0,0 +1,203 @@
+/*-
+ * Copyright (c) 2021 Tim Creech <tcreech@tcreech.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/soundcard.h>
+
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sndio.h>
+
+#include "backend.h"
+#include "int.h"
+
+static struct sio_hdl *
+get_sio_hdl(struct voss_backend *pbe)
+{
+ if (pbe)
+ return (pbe->arg);
+
+ return (NULL);
+}
+
+static void
+sndio_close(struct voss_backend *pbe)
+{
+ if (!pbe)
+ return;
+
+ if (get_sio_hdl(pbe))
+ sio_close(get_sio_hdl(pbe));
+}
+
+static int
+sndio_get_signedness(int *fmt)
+{
+ int s_fmt = *fmt & (VPREFERRED_SLE_AFMT | VPREFERRED_SBE_AFMT);
+
+ if (s_fmt) {
+ *fmt = s_fmt;
+ return (1);
+ }
+ *fmt = *fmt & (VPREFERRED_ULE_AFMT | VPREFERRED_UBE_AFMT);
+ return (0);
+}
+
+static int
+sndio_get_endianness_is_le(int *fmt)
+{
+ int le_fmt = *fmt & (VPREFERRED_SLE_AFMT | VPREFERRED_ULE_AFMT);
+
+ if (le_fmt) {
+ *fmt = le_fmt;
+ return (1);
+ }
+ *fmt = *fmt & (VPREFERRED_SBE_AFMT | VPREFERRED_UBE_AFMT);
+ return (0);
+}
+
+static int
+sndio_get_bits(int *fmt)
+{
+ if (*fmt & AFMT_16BIT)
+ return (16);
+ if (*fmt & AFMT_24BIT)
+ return (24);
+ if (*fmt & AFMT_32BIT)
+ return (32);
+ if (*fmt & AFMT_8BIT)
+ return (8);
+ return (-1);
+ /* TODO AFMT_BIT */
+}
+
+static int
+sndio_open(struct voss_backend *pbe, const char *devname,
+ int samplerate, int bufsize, int *pchannels, int *pformat, int direction)
+{
+ const char *sndio_name = devname + strlen("/dev/sndio/");
+
+ int sig = sndio_get_signedness(pformat);
+ int le = sndio_get_endianness_is_le(pformat);
+ int bits = sndio_get_bits(pformat);
+
+ if (bits == -1) {
+ warn("unsupported format precision");
+ return (-1);
+ }
+
+ struct sio_hdl *hdl = sio_open(sndio_name, direction, 0);
+
+ if (hdl == 0) {
+ warn("sndio: failed to open device");
+ return (-1);
+ }
+
+ struct sio_par par;
+
+ sio_initpar(&par);
+ par.pchan = *pchannels;
+ par.sig = sig;
+ par.bits = bits;
+ par.bps = SIO_BPS(bits);
+ par.le = le;
+ par.rate = samplerate;
+ par.appbufsz = bufsize;
+ par.xrun = SIO_SYNC;
+ if (!sio_setpar(hdl, &par))
+ errx(1, "internal error, sio_setpar() failed");
+ if (!sio_getpar(hdl, &par))
+ errx(1, "internal error, sio_getpar() failed");
+ if ((int)par.pchan != *pchannels)
+ errx(1, "couldn't set number of channels");
+ if ((int)par.sig != sig || (int)par.bits != bits || (int)par.le != le)
+ errx(1, "couldn't set format");
+ if ((int)par.bits != bits)
+ errx(1, "couldn't set precision");
+ if ((int)par.rate < samplerate * 995 / 1000 ||
+ (int)par.rate > samplerate * 1005 / 1000)
+ errx(1, "couldn't set rate");
+ if (par.xrun != SIO_SYNC)
+ errx(1, "couldn't set xun policy");
+
+ /* Save the device handle with the backend */
+ pbe->arg = hdl;
+
+ /* Start the device. */
+ if (!sio_start(hdl))
+ errx(1, "couldn't start device");
+
+ return (0);
+}
+
+static int
+sndio_open_play(struct voss_backend *pbe, const char *devname,
+ int samplerate, int bufsize, int *pchannels, int *pformat)
+{
+ return (sndio_open(pbe, devname, samplerate, bufsize, pchannels, pformat, SIO_PLAY));
+}
+
+static int
+sndio_open_rec(struct voss_backend *pbe, const char *devname,
+ int samplerate, int bufsize, int *pchannels, int *pformat)
+{
+ return (sndio_open(pbe, devname, samplerate, bufsize, pchannels, pformat, SIO_REC));
+}
+
+static int
+sndio_play_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ return (sio_write(get_sio_hdl(pbe), ptr, len));
+}
+
+static int
+sndio_rec_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ return (sio_read(get_sio_hdl(pbe), ptr, len));
+}
+
+static void
+sndio_delay(struct voss_backend *pbe __unused, int *pdelay)
+{
+ *pdelay = -1;
+}
+
+struct voss_backend voss_backend_sndio_rec = {
+ .open = sndio_open_rec,
+ .close = sndio_close,
+ .transfer = sndio_rec_transfer,
+ .delay = sndio_delay,
+ .fd = -1,
+};
+
+struct voss_backend voss_backend_sndio_play = {
+ .open = sndio_open_play,
+ .close = sndio_close,
+ .transfer = sndio_play_transfer,
+ .delay = sndio_delay,
+ .fd = -1,
+};