--- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -30,6 +30,9 @@ #else #include #endif +#ifdef __FreeBSD__ +#include +#endif #include "qemu-common.h" #include "host-utils.h" #include "qemu-char.h" @@ -240,6 +243,31 @@ static void oss_dump_info (struct oss_pa } #endif +#ifdef __FreeBSD__ +/* + * Get FreeBSD's internal sound driver version, this is the same as + * SND_DRV_VERSION in src/sys/dev/sound/version.h . + * + * Returns 0 on error. + */ +static unsigned +freebsd_snd_version(void) +{ + static unsigned snd_version = 0; + char buf[64]; + size_t buflen = sizeof(buf); + + if (snd_version) { + return snd_version; + } + if (sysctlbyname("hw.snd.version", buf, &buflen, NULL, 0) == -1) { + return 0; + } + snd_version = strtoul(buf, (char **)NULL, 10); + return snd_version; +} +#endif + static int oss_open (int in, struct oss_params *req, struct oss_params *obt, int *pfd) { @@ -288,8 +316,26 @@ static int oss_open (int in, struct oss_ #ifdef USE_DSP_POLICY if (conf.policy >= 0) { int version; +#ifdef __FreeBSD__ + /* + * Looks like atm (20100109) FreeBSD knows OSS_GETVERSION + * since 7.x, but currently only on the mixer device (or in + * the Linuxolator), and in the native version that part of + * the code is in fact never reached so the ioctl fails anyway. + * Until this is fixed, check the internal version as returned + * by the hw.snd.version sysctl. + * TODO: Check how this works on debian/kFreeBSD + * (#ifdef __FreeBSD_kernel__) + */ + unsigned sndversion = freebsd_snd_version(); +#endif - if (ioctl (fd, OSS_GETVERSION, &version)) { + if (ioctl (fd, OSS_GETVERSION, &version) +#ifdef __FreeBSD__ + && ((version = (sndversion >= 2007060100 ? 0x040000 : 0)), + (sndversion == 0)) +#endif + ) { oss_logerr2 (errno, typ, "Failed to get OSS version\n"); } else {