Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
599a2005
提交
599a2005
authored
11月 26, 2010
作者:
Giovanni Maruzzelli
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
skypopen: adding osscuse directory, lot of news to come in some days ;)
上级
c7aefe93
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
4977 行增加
和
0 行删除
+4977
-0
98-osscuse.rules
src/mod/endpoints/mod_skypopen/osscuse/98-osscuse.rules
+7
-0
LICENSE
src/mod/endpoints/mod_skypopen/osscuse/LICENSE
+339
-0
Makefile
src/mod/endpoints/mod_skypopen/osscuse/Makefile
+69
-0
README
src/mod/endpoints/mod_skypopen/osscuse/README
+119
-0
ossp-alsap.c
src/mod/endpoints/mod_skypopen/osscuse/ossp-alsap.c
+613
-0
ossp-slave.c
src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.c
+250
-0
ossp-slave.h
src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.h
+28
-0
ossp-util.c
src/mod/endpoints/mod_skypopen/osscuse/ossp-util.c
+369
-0
ossp-util.h
src/mod/endpoints/mod_skypopen/osscuse/ossp-util.h
+609
-0
ossp.c
src/mod/endpoints/mod_skypopen/osscuse/ossp.c
+83
-0
ossp.h
src/mod/endpoints/mod_skypopen/osscuse/ossp.h
+117
-0
osspd.c
src/mod/endpoints/mod_skypopen/osscuse/osspd.c
+2374
-0
没有找到文件。
src/mod/endpoints/mod_skypopen/osscuse/98-osscuse.rules
0 → 100644
浏览文件 @
599a2005
# Since these devices are not part of 'sound' subsystem the group is forced
# to audio by name
# /dev/cuse can stay mode 0660 root:root since osspd is run as root
# and drops privileges to user level when opened by user
KERNEL=="dsp", GROUP="audio"
KERNEL=="mixer", GROUP="audio"
KERNEL=="adsp", GROUP="audio"
src/mod/endpoints/mod_skypopen/osscuse/LICENSE
0 → 100644
浏览文件 @
599a2005
差异被折叠。
点击展开。
src/mod/endpoints/mod_skypopen/osscuse/Makefile
0 → 100644
浏览文件 @
599a2005
# These can be overridden if needed
# DESTDIR is completely respected
CC
:=
gcc
AR
:=
ar
CFLAGS
:=
-Wall
$(CFLAGS)
XLDFLAGS
:=
$(LDFLAGS)
LDFLAGS
:=
-L
.
-lossp
$(LDFLAGS)
prefix
:=
/usr/local
DESTDIR
:=
UDEVDIR
:=
/etc/udev/rules.d
ifeq
"$(origin OSSPD_CFLAGS)"
"undefined"
OSSPD_CFLAGS
:=
$(
shell
pkg-config
--cflags
fuse
)
endif
ifeq
"$(origin OSSPD_LDFLAGS)"
"undefined"
OSSPD_LDFLAGS
:=
$(
shell
pkg-config
--libs
fuse
)
endif
ifeq
"$(origin OSSP_PADSP_CFLAGS)"
"undefined"
OSSP_PADSP_CFLAGS
:=
$(
shell
pkg-config
--cflags
libpulse
)
endif
ifeq
"$(origin OSSP_PADSP_LDFLAGS)"
"undefined"
OSSP_PADSP_LDFLAGS
:=
$(
shell
pkg-config
--libs
libpulse
)
endif
ifeq
"$(origin OSSP_ALSAP_CFLAGS)"
"undefined"
OSSP_ALSAP_CFLAGS
:=
$(
shell
pkg-config
--libs
alsa
)
endif
ifeq
"$(origin OSSP_ALSAP_LDFLAGS)"
"undefined"
OSSP_ALSAP_LDFLAGS
:=
$(
shell
pkg-config
--libs
alsa
)
endif
headers
:=
ossp.h ossp-util.h ossp-slave.h
#all: osspd ossp-padsp ossp-alsap
all
:
osspd ossp-alsap
install
:
mkdir
-p
$(DESTDIR)$(prefix)
/sbin
install
-m755
osspd ossp-padsp ossp-alsap
$(DESTDIR)$(prefix)
/sbin
mkdir
-p
$(DESTDIR)$(UDEVDIR)
install
-m644
98-osscuse.rules
$(DESTDIR)$(UDEVDIR)
libossp.a
:
ossp.c ossp.h ossp-util.c ossp-util.h ossp-slave.c ossp-slave.h
$(CC)
$(CFLAGS)
-c
-o
ossp.o ossp.c
$(CC)
$(CFLAGS)
-c
-o
ossp-util.o ossp-util.c
$(CC)
$(CFLAGS)
-c
-o
ossp-slave.o ossp-slave.c
$(AR)
rc
$@
ossp.o ossp-util.o ossp-slave.o
osspd
:
osspd.c libossp.a $(headers)
$(CC)
$(CFLAGS)
$(OSSPD_CFLAGS)
-o
$@
$<
$(OSSPD_LDFLAGS)
$(LDFLAGS)
ossp-padsp
:
ossp-padsp.c libossp.a $(headers)
$(CC)
$(CFLAGS)
$(OSSP_PADSP_CFLAGS)
-o
$@
$<
$(OSSP_PADSP_LDFLAGS)
$(LDFLAGS)
ossp-alsap
:
ossp-alsap.c libossp.a $(headers)
$(CC)
$(CFLAGS)
$(OSSP_ALSAP_CFLAGS)
-o
$@
$<
$(OSSP_ALSAP_LDFLAGS)
$(LDFLAGS)
osstest
:
osstest.c
$(CC)
$(CFLAGS)
-o
$@
$<
$(XLDFLAGS)
test
:
osstest
@
./osstest
clean
:
rm
-f
*
.o
*
.a osspd ossp-padsp ossp-alsap osstest
src/mod/endpoints/mod_skypopen/osscuse/README
0 → 100644
浏览文件 @
599a2005
OSS Proxy - emulate OSS device using CUSE
Copyright (C) 2008-2009 SUSE Linux Products GmbH
Copyright (C) 2008-2009 Tejun Heo <tj@kernel.org>
1. What is it?
--------------
Well, first, OSS refers to Open Sound System. If it still doesn't
ring a bell, think /dev/dsp, /dev/adsp and /dev/mixer.
Currently, Linux supports two audio programming interface - ALSA and
OSS. The latter one is deprecated and has been that way for a long
time but there still are applications which still use them including
UML (usermode Linux) host sound support.
ALSA contains OSS emulation but sadly the emulation is behind
multiplexing layer (which is in userland) which means that if your
sound card doesn't support multiple audio streams, only either one of
ALSA or OSS interface would be usable at any given moment.
There have been also attempts to emulate OSS in userland using dynamic
library preloading - aoss and more recently padsp. This works for
many applications but it's just not easy to emulate everything using
the technique. Things like polling, signals, forking, privilege
changes make it very difficult to emulate things reliably.
OSS Proxy uses CUSE (extension of FUSE allowing character devices to
be implemented in userspace) to implement OSS interface - /dev/dsp,
/dev/adsp and /dev/mixer. From the POV of the applications, these
devices are proper character devices and behave exactly the same way
so it can be made quite versatile.
2. Hmmm... So, how does the whole thing work?
---------------------------------------------
The OSS Proxy daemon - osspd - should be started first. Note that
osspd will fail to start if sound device number regions are already
occupied. You'll need to turn off OSS or its emulation[1].
On startup, osspd creates /dev/dsp, /dev/adsp and /dev/mixer using
CUSE. When an application access one of the devices, all IOs are
redirected to osspd via CUSE. Upon receiving a new DSP open request,
osspd creates a slave process which drops the root privilege and
assumes the opening process's credentials. After handshaking, osspd
forwards all relevant IOs to the slave which is responsible for
actually playing the sound.
Currently there's only one slave implemented - ossp-padsp, which as
the name suggests forwards (again) the sound to pulseaudio. To sum
up, the whole pipe looks like the following.
App <-> /dev/dsp <-> CUSE <-> osspd <-> ossp-padsp <-> pulseaudio
Which is a lot of forwarding, but on modern machines, it won't be too
noticeable.
3. What works?
--------------
Well, MIDI part isn't implemented and I doubt it will be in any near
future but except that everything should work. Playing, recording,
5.1ch, A-V syncing, all should work. If not, it's a bug, so please
report.
The mixer behaves a bit differently tho. In the original OSS,
/dev/mixer is the hardware mixer, so adjusting volumes there affects
all audio streams. When using ossp, each process group gets its own
mixer and the mixer always contains only two knobs - PCM and IGAIN.
Combined with per-stream volume control of pulseaudio, this scheme
works quite well for applications with embedded volume control
although it makes standalone OSS mixer programs virtually useless[2].
4. How do I use it?
-------------------
First you need CUSE support in kernel which might land on 2.6.28 with
sufficient luck[3] and then you also need libfuse which supports
CUSE[4]. Once you have both, it should be easy. First build it by
running `make'. You can set OSSPD_CFLAGS, OSSPD_LDFLAGS,
OSSP_PADSP_CFLAGS and OSSP_PADSP_LDFLAGS if you have stuff at
non-default locations.
After build completes, there will be two executables - `osspd' and
`ossp-padsp'. Just copy them to where other system executables live.
Specific location doesn't matter as long as both files end up in the
same directory.
Execute `osspd'. It will create the device files and you're all set.
`osspd' uses syslog with LOG_DAEMON facility, so if something doesn't
work take a look at what osspd complains about.
[1] As of this writing, turning on any sound support makes the
soundcore module claim OSS device regions. Patch to make it claim
OSS device regions only when OSS support or emulation is enabled
is scheduled for 2.6.28. Even with the patch, soundcore will
claim OSS device regions if OSS support or ALSA OSS emulation is
enabled. Make sure they're turned off.
[2] If you have a strong reason to use standalone OSS mixer program,
you can play some shell tricks to put it into the same process
group as the target audio application. e.g. To use aumix with
mpg123 - `(mpg123 asdf.mp3 > /dev/null 2>&1 & aumix)', but
seriously, just use PA or ALSA one.
[3] For the time being, here's the git tree with all the necessary
changes. This tree is base on top of 2.6.27-rc3.
http://git.kernel.org/?p=linux/kernel/git/tj/misc.git;a=shortlog;h=cuse
git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git cuse
[4] And libfuse with the modifications can be found at...
http://userweb.kernel.org/~tj/ossp/fuse-cuse.tar.gz
src/mod/endpoints/mod_skypopen/osscuse/ossp-alsap.c
0 → 100644
浏览文件 @
599a2005
差异被折叠。
点击展开。
src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.c
0 → 100644
浏览文件 @
599a2005
/*
* ossp-slave - OSS Proxy: Common codes for slaves
*
* Copyright (C) 2008-2010 SUSE Linux Products GmbH
* Copyright (C) 2008-2010 Tejun Heo <tj@kernel.org>
*
* This file is released under the GPLv2.
*/
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <signal.h>
#include "ossp-slave.h"
static
const
char
*
usage
=
"usage: ossp-SLAVE [options]
\n
"
"
\n
"
"proxies commands from osspd to pulseaudio
\n
"
"
\n
"
"options:
\n
"
" -u UID uid to use
\n
"
" -g GID gid to use
\n
"
" -c CMD_FD fd to receive commands from osspd
\n
"
" -n NOTIFY_FD fd to send async notifications to osspd
\n
"
" -m MMAP_FD fd to use for mmap
\n
"
" -o MMAP_OFFSET mmap offset
\n
"
" -s MMAP_SIZE mmap size
\n
"
" -l LOG_LEVEL set log level
\n
"
" -t enable log timestamps
\n
"
;
char
ossp_user_name
[
OSSP_USER_NAME_LEN
];
int
ossp_cmd_fd
=
-
1
,
ossp_notify_fd
=
-
1
;
void
*
ossp_mmap_addr
[
2
];
void
ossp_slave_init
(
int
argc
,
char
**
argv
)
{
int
have_uid
=
0
,
have_gid
=
0
;
uid_t
uid
;
gid_t
gid
;
int
mmap_fd
=
-
1
;
off_t
mmap_off
=
0
;
size_t
mmap_size
=
0
;
int
opt
;
struct
passwd
*
pw
,
pw_buf
;
struct
sigaction
sa
;
char
pw_sbuf
[
sysconf
(
_SC_GETPW_R_SIZE_MAX
)];
while
((
opt
=
getopt
(
argc
,
argv
,
"u:g:c:n:m:o:s:l:t"
))
!=
-
1
)
{
switch
(
opt
)
{
case
'u'
:
have_uid
=
1
;
uid
=
strtol
(
optarg
,
NULL
,
0
);
break
;
case
'g'
:
have_gid
=
1
;
gid
=
strtol
(
optarg
,
NULL
,
0
);
break
;
case
'c'
:
ossp_cmd_fd
=
strtol
(
optarg
,
NULL
,
0
);
break
;
case
'n'
:
ossp_notify_fd
=
strtol
(
optarg
,
NULL
,
0
);
break
;
case
'm'
:
mmap_fd
=
strtol
(
optarg
,
NULL
,
0
);
break
;
case
'o'
:
mmap_off
=
strtoull
(
optarg
,
NULL
,
0
);
break
;
case
's'
:
mmap_size
=
strtoul
(
optarg
,
NULL
,
0
);
break
;
case
'l'
:
ossp_log_level
=
strtol
(
optarg
,
NULL
,
0
);
break
;
case
't'
:
ossp_log_timestamp
=
1
;
break
;
}
}
if
(
!
have_uid
||
!
have_gid
||
ossp_cmd_fd
<
0
||
ossp_notify_fd
<
0
)
{
fprintf
(
stderr
,
usage
);
_exit
(
1
);
}
snprintf
(
ossp_user_name
,
sizeof
(
ossp_user_name
),
"uid%d"
,
uid
);
if
(
getpwuid_r
(
uid
,
&
pw_buf
,
pw_sbuf
,
sizeof
(
pw_sbuf
),
&
pw
)
==
0
)
snprintf
(
ossp_user_name
,
sizeof
(
ossp_user_name
),
"%s"
,
pw
->
pw_name
);
snprintf
(
ossp_log_name
,
sizeof
(
ossp_log_name
),
"ossp-padsp[%s:%d]"
,
ossp_user_name
,
getpid
());
if
(
mmap_fd
>=
0
)
{
void
*
p
;
if
(
!
mmap_off
||
!
mmap_size
)
{
fprintf
(
stderr
,
usage
);
_exit
(
1
);
}
p
=
mmap
(
NULL
,
mmap_size
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
mmap_fd
,
mmap_off
);
if
(
p
==
MAP_FAILED
)
fatal_e
(
-
errno
,
"mmap failed"
);
ossp_mmap_addr
[
PLAY
]
=
p
;
ossp_mmap_addr
[
REC
]
=
p
+
mmap_size
/
2
;
close
(
mmap_fd
);
}
/* mmap done, drop privileges */
if
(
setresgid
(
gid
,
gid
,
gid
)
||
setresuid
(
uid
,
uid
,
uid
))
fatal_e
(
-
errno
,
"failed to drop privileges"
);
/* block SIGPIPE */
memset
(
&
sa
,
0
,
sizeof
(
sa
));
sa
.
sa_handler
=
SIG_IGN
;
if
(
sigaction
(
SIGPIPE
,
&
sa
,
NULL
))
fatal_e
(
-
errno
,
"failed to ignore SIGPIPE"
);
}
int
ossp_slave_process_command
(
int
cmd_fd
,
ossp_action_fn_t
const
*
action_fn_tbl
,
int
(
*
action_pre_fn
)(
void
),
void
(
*
action_post_fn
)(
void
))
{
static
struct
sized_buf
carg_sbuf
=
{
},
rarg_sbuf
=
{
};
static
struct
sized_buf
din_sbuf
=
{
},
dout_sbuf
=
{
};
struct
ossp_cmd
cmd
;
int
fd
=
-
1
;
char
cmsg_buf
[
CMSG_SPACE
(
sizeof
(
fd
))];
struct
iovec
iov
=
{
&
cmd
,
sizeof
(
cmd
)
};
struct
msghdr
msg
=
{
.
msg_iov
=
&
iov
,
.
msg_iovlen
=
1
,
.
msg_control
=
cmsg_buf
,
.
msg_controllen
=
sizeof
(
cmsg_buf
)
};
struct
cmsghdr
*
cmsg
;
size_t
carg_size
,
din_size
,
rarg_size
,
dout_size
;
char
*
carg
=
NULL
,
*
din
=
NULL
,
*
rarg
=
NULL
,
*
dout
=
NULL
;
struct
ossp_reply
reply
=
{
.
magic
=
OSSP_REPLY_MAGIC
};
ssize_t
ret
;
ret
=
recvmsg
(
cmd_fd
,
&
msg
,
0
);
if
(
ret
==
0
)
return
0
;
if
(
ret
<
0
)
{
ret
=
-
errno
;
err_e
(
ret
,
"failed to read command channel"
);
return
ret
;
}
if
(
ret
!=
sizeof
(
cmd
))
{
err
(
"command struct size mismatch (%zu, should be %zu)"
,
ret
,
sizeof
(
cmd
));
return
-
EINVAL
;
}
if
(
cmd
.
magic
!=
OSSP_CMD_MAGIC
)
{
err
(
"illegal command magic 0x%x"
,
cmd
.
magic
);
return
-
EINVAL
;
}
for
(
cmsg
=
CMSG_FIRSTHDR
(
&
msg
);
cmsg
;
cmsg
=
CMSG_NXTHDR
(
&
msg
,
cmsg
))
{
if
(
cmsg
->
cmsg_level
==
SOL_SOCKET
&&
cmsg
->
cmsg_type
==
SCM_RIGHTS
)
fd
=
*
(
int
*
)
CMSG_DATA
(
cmsg
);
else
{
err
(
"unknown cmsg %d:%d received (opcode %d)"
,
cmsg
->
cmsg_level
,
cmsg
->
cmsg_type
,
cmd
.
opcode
);
return
-
EINVAL
;
}
}
if
(
cmd
.
opcode
>=
OSSP_NR_OPCODES
)
{
err
(
"unknown opcode %d"
,
cmd
.
opcode
);
return
-
EINVAL
;
}
carg_size
=
ossp_arg_sizes
[
cmd
.
opcode
].
carg_size
;
din_size
=
cmd
.
din_size
;
rarg_size
=
ossp_arg_sizes
[
cmd
.
opcode
].
rarg_size
;
dout_size
=
cmd
.
dout_size
;
if
((
fd
>=
0
)
!=
ossp_arg_sizes
[
cmd
.
opcode
].
has_fd
)
{
err
(
"fd=%d unexpected for opcode %d"
,
fd
,
cmd
.
opcode
);
return
-
EINVAL
;
}
if
(
ensure_sbuf_size
(
&
carg_sbuf
,
carg_size
)
||
ensure_sbuf_size
(
&
din_sbuf
,
din_size
)
||
ensure_sbuf_size
(
&
rarg_sbuf
,
rarg_size
)
||
ensure_sbuf_size
(
&
dout_sbuf
,
dout_size
))
{
err
(
"failed to allocate command buffers"
);
return
-
ENOMEM
;
}
if
(
carg_size
)
{
carg
=
carg_sbuf
.
buf
;
ret
=
read_fill
(
cmd_fd
,
carg
,
carg_size
);
if
(
ret
<
0
)
return
ret
;
}
if
(
din_size
)
{
din
=
din_sbuf
.
buf
;
ret
=
read_fill
(
cmd_fd
,
din
,
din_size
);
if
(
ret
<
0
)
return
ret
;
}
if
(
rarg_size
)
rarg
=
rarg_sbuf
.
buf
;
if
(
dout_size
)
dout
=
dout_sbuf
.
buf
;
ret
=
-
EINVAL
;
if
(
action_fn_tbl
[
cmd
.
opcode
])
{
ret
=
action_pre_fn
();
if
(
ret
==
0
)
{
ret
=
action_fn_tbl
[
cmd
.
opcode
](
cmd
.
opcode
,
carg
,
din
,
din_size
,
rarg
,
dout
,
&
dout_size
,
fd
);
action_post_fn
();
}
}
reply
.
result
=
ret
;
if
(
ret
>=
0
)
reply
.
dout_size
=
dout_size
;
else
{
rarg_size
=
0
;
dout_size
=
0
;
}
if
(
write_fill
(
cmd_fd
,
&
reply
,
sizeof
(
reply
))
<
0
||
write_fill
(
cmd_fd
,
rarg
,
rarg_size
)
<
0
||
write_fill
(
cmd_fd
,
dout
,
dout_size
)
<
0
)
return
-
EIO
;
return
1
;
}
src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.h
0 → 100644
浏览文件 @
599a2005
/*
* ossp-slave - OSS Proxy: Common codes for slaves
*
* Copyright (C) 2008-2010 SUSE Linux Products GmbH
* Copyright (C) 2008-2010 Tejun Heo <tj@kernel.org>
*
* This file is released under the GPLv2.
*/
#ifndef _OSSP_SLAVE_H
#define _OSSP_SLAVE_H
#include "ossp.h"
#include "ossp-util.h"
#define OSSP_USER_NAME_LEN 128
extern
char
ossp_user_name
[
OSSP_USER_NAME_LEN
];
extern
int
ossp_cmd_fd
,
ossp_notify_fd
;
extern
void
*
ossp_mmap_addr
[
2
];
void
ossp_slave_init
(
int
argc
,
char
**
argv
);
int
ossp_slave_process_command
(
int
cmd_fd
,
ossp_action_fn_t
const
*
action_fn_tbl
,
int
(
*
action_pre_fn
)(
void
),
void
(
*
action_post_fn
)(
void
));
#endif
/* _OSSP_SLAVE_H */
src/mod/endpoints/mod_skypopen/osscuse/ossp-util.c
0 → 100644
浏览文件 @
599a2005
/*
* ossp-util - OSS Proxy: Common utilities
*
* Copyright (C) 2008-2010 SUSE Linux Products GmbH
* Copyright (C) 2008-2010 Tejun Heo <tj@kernel.org>
*
* This file is released under the GPLv2.
*/
#include <ctype.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <syslog.h>
#include <unistd.h>
#include "ossp-util.h"
#define BIT(nr) (1UL << (nr))
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
char
ossp_log_name
[
OSSP_LOG_NAME_LEN
];
int
ossp_log_level
=
OSSP_LOG_DFL
;
int
ossp_log_timestamp
;
static
const
char
*
severity_strs
[]
=
{
[
OSSP_LOG_CRIT
]
=
"CRIT"
,
[
OSSP_LOG_ERR
]
=
" ERR"
,
[
OSSP_LOG_WARN
]
=
"WARN"
,
[
OSSP_LOG_INFO
]
=
NULL
,
[
OSSP_LOG_DBG0
]
=
"DBG0"
,
[
OSSP_LOG_DBG1
]
=
"DBG1"
,
};
static
int
severity_map
[]
=
{
[
OSSP_LOG_CRIT
]
=
LOG_ERR
,
[
OSSP_LOG_ERR
]
=
LOG_ERR
,
[
OSSP_LOG_WARN
]
=
LOG_WARNING
,
[
OSSP_LOG_INFO
]
=
LOG_INFO
,
[
OSSP_LOG_DBG0
]
=
LOG_DEBUG
,
[
OSSP_LOG_DBG1
]
=
LOG_DEBUG
,
};
void
log_msg
(
int
severity
,
const
char
*
fmt
,
...)
{
static
int
syslog_opened
=
0
;
char
buf
[
1024
];
size_t
len
=
sizeof
(
buf
),
off
=
0
;
va_list
ap
;
if
(
severity
>
abs
(
ossp_log_level
))
return
;
if
(
ossp_log_level
<
0
&&
!
syslog_opened
)
openlog
(
ossp_log_name
,
0
,
LOG_DAEMON
);
assert
(
severity
>=
0
&&
severity
<
ARRAY_SIZE
(
severity_strs
));
if
(
ossp_log_timestamp
)
{
static
uint64_t
start
;
uint64_t
now
;
struct
timeval
tv
;
gettimeofday
(
&
tv
,
NULL
);
now
=
tv
.
tv_sec
*
1000
+
tv
.
tv_usec
/
1000
;
if
(
!
start
)
start
=
now
;
off
+=
snprintf
(
buf
+
off
,
len
-
off
,
"<%08"
PRIu64
"> "
,
now
-
start
);
}
if
(
ossp_log_level
>
0
)
{
char
sev_buf
[
16
]
=
""
;
if
(
severity_strs
[
severity
])
snprintf
(
sev_buf
,
sizeof
(
sev_buf
),
" %s"
,
severity_strs
[
severity
]);
off
+=
snprintf
(
buf
+
off
,
len
-
off
,
"%s%s: "
,
ossp_log_name
,
sev_buf
);
}
else
if
(
severity_strs
[
severity
])
off
+=
snprintf
(
buf
+
off
,
len
-
off
,
"%s "
,
severity_strs
[
severity
]);
va_start
(
ap
,
fmt
);
off
+=
vsnprintf
(
buf
+
off
,
len
-
off
,
fmt
,
ap
);
va_end
(
ap
);
off
+=
snprintf
(
buf
+
off
,
len
-
off
,
"
\n
"
);
if
(
ossp_log_level
>
0
)
fputs
(
buf
,
stderr
);
else
syslog
(
severity_map
[
severity
],
"%s"
,
buf
);
}
int
read_fill
(
int
fd
,
void
*
buf
,
size_t
size
)
{
while
(
size
)
{
ssize_t
ret
;
int
rc
;
ret
=
read
(
fd
,
buf
,
size
);
if
(
ret
<=
0
)
{
if
(
ret
==
0
)
rc
=
-
EIO
;
else
rc
=
-
errno
;
err_e
(
rc
,
"failed to read_fill %zu bytes from fd %d"
,
size
,
fd
);
return
rc
;
}
buf
+=
ret
;
size
-=
ret
;
}
return
0
;
}
int
write_fill
(
int
fd
,
const
void
*
buf
,
size_t
size
)
{
while
(
size
)
{
ssize_t
ret
;
int
rc
;
ret
=
write
(
fd
,
buf
,
size
);
if
(
ret
<=
0
)
{
if
(
ret
==
0
)
rc
=
-
EIO
;
else
rc
=
-
errno
;
err_e
(
rc
,
"failed to write_fill %zu bytes to fd %d"
,
size
,
fd
);
return
rc
;
}
buf
+=
ret
;
size
-=
ret
;
}
return
0
;
}
void
ring_fill
(
struct
ring_buf
*
ring
,
const
void
*
buf
,
size_t
size
)
{
size_t
tail
;
assert
(
ring_space
(
ring
)
>=
size
);
tail
=
(
ring
->
head
+
ring
->
size
-
ring
->
bytes
)
%
ring
->
size
;
if
(
ring
->
head
>=
tail
)
{
size_t
todo
=
min
(
size
,
ring
->
size
-
ring
->
head
);
memcpy
(
ring
->
buf
+
ring
->
head
,
buf
,
todo
);
ring
->
head
=
(
ring
->
head
+
todo
)
%
ring
->
size
;
ring
->
bytes
+=
todo
;
buf
+=
todo
;
size
-=
todo
;
}
assert
(
ring
->
size
-
ring
->
head
>=
size
);
memcpy
(
ring
->
buf
+
ring
->
head
,
buf
,
size
);
ring
->
head
+=
size
;
ring
->
bytes
+=
size
;
}
void
*
ring_data
(
struct
ring_buf
*
ring
,
size_t
*
sizep
)
{
size_t
tail
;
if
(
!
ring
->
bytes
)
return
NULL
;
tail
=
(
ring
->
head
+
ring
->
size
-
ring
->
bytes
)
%
ring
->
size
;
*
sizep
=
min
(
ring
->
bytes
,
ring
->
size
-
tail
);
return
ring
->
buf
+
tail
;
}
int
ring_resize
(
struct
ring_buf
*
ring
,
size_t
new_size
)
{
struct
ring_buf
new_ring
=
{
.
size
=
new_size
};
void
*
p
;
size_t
size
;
if
(
ring_bytes
(
ring
)
>
new_size
)
return
-
ENOSPC
;
new_ring
.
buf
=
calloc
(
1
,
new_size
);
if
(
new_size
&&
!
new_ring
.
buf
)
return
-
ENOMEM
;
while
((
p
=
ring_data
(
ring
,
&
size
)))
{
ring_fill
(
&
new_ring
,
p
,
size
);
ring_consume
(
ring
,
size
);
}
free
(
ring
->
buf
);
*
ring
=
new_ring
;
return
0
;
}
int
ensure_sbuf_size
(
struct
sized_buf
*
sbuf
,
size_t
size
)
{
char
*
new_buf
;
if
(
sbuf
->
size
>=
size
)
return
0
;
new_buf
=
realloc
(
sbuf
->
buf
,
size
);
if
(
size
&&
!
new_buf
)
return
-
ENOMEM
;
sbuf
->
buf
=
new_buf
;
sbuf
->
size
=
size
;
return
0
;
}
static
unsigned
long
__ffs
(
unsigned
long
word
)
{
int
num
=
0
;
if
(
BITS_PER_LONG
==
64
)
{
if
((
word
&
0xffffffff
)
==
0
)
{
num
+=
32
;
word
>>=
32
;
}
}
if
((
word
&
0xffff
)
==
0
)
{
num
+=
16
;
word
>>=
16
;
}
if
((
word
&
0xff
)
==
0
)
{
num
+=
8
;
word
>>=
8
;
}
if
((
word
&
0xf
)
==
0
)
{
num
+=
4
;
word
>>=
4
;
}
if
((
word
&
0x3
)
==
0
)
{
num
+=
2
;
word
>>=
2
;
}
if
((
word
&
0x1
)
==
0
)
num
+=
1
;
return
num
;
}
#define ffz(x) __ffs(~(x))
unsigned
long
find_next_zero_bit
(
const
unsigned
long
*
addr
,
unsigned
long
size
,
unsigned
long
offset
)
{
const
unsigned
long
*
p
=
addr
+
BITOP_WORD
(
offset
);
unsigned
long
result
=
offset
&
~
(
BITS_PER_LONG
-
1
);
unsigned
long
tmp
;
if
(
offset
>=
size
)
return
size
;
size
-=
result
;
offset
%=
BITS_PER_LONG
;
if
(
offset
)
{
tmp
=
*
(
p
++
);
tmp
|=
~
0UL
>>
(
BITS_PER_LONG
-
offset
);
if
(
size
<
BITS_PER_LONG
)
goto
found_first
;
if
(
~
tmp
)
goto
found_middle
;
size
-=
BITS_PER_LONG
;
result
+=
BITS_PER_LONG
;
}
while
(
size
&
~
(
BITS_PER_LONG
-
1
))
{
if
(
~
(
tmp
=
*
(
p
++
)))
goto
found_middle
;
result
+=
BITS_PER_LONG
;
size
-=
BITS_PER_LONG
;
}
if
(
!
size
)
return
result
;
tmp
=
*
p
;
found_first:
tmp
|=
~
0UL
<<
size
;
if
(
tmp
==
~
0UL
)
/* Are any bits zero? */
return
result
+
size
;
/* Nope. */
found_middle:
return
result
+
ffz
(
tmp
);
}
void
__set_bit
(
int
nr
,
volatile
unsigned
long
*
addr
)
{
unsigned
long
mask
=
BIT_MASK
(
nr
);
unsigned
long
*
p
=
((
unsigned
long
*
)
addr
)
+
BIT_WORD
(
nr
);
*
p
|=
mask
;
}
void
__clear_bit
(
int
nr
,
volatile
unsigned
long
*
addr
)
{
unsigned
long
mask
=
BIT_MASK
(
nr
);
unsigned
long
*
p
=
((
unsigned
long
*
)
addr
)
+
BIT_WORD
(
nr
);
*
p
&=
~
mask
;
}
int
get_proc_self_info
(
pid_t
pid
,
pid_t
*
ppid_r
,
char
*
cmd_buf
,
size_t
cmd_buf_sz
)
{
char
path
[
64
],
buf
[
4096
];
int
fd
=
-
1
;
char
*
cmd_start
,
*
cmd_end
,
*
ppid_start
,
*
end
;
ssize_t
ret
;
pid_t
ppid
;
int
i
,
rc
;
snprintf
(
path
,
sizeof
(
path
),
"/proc/%ld/stat"
,
(
long
)
pid
);
fd
=
open
(
path
,
O_RDONLY
);
if
(
fd
<
0
)
{
rc
=
-
errno
;
goto
out
;
}
ret
=
read
(
fd
,
buf
,
sizeof
(
buf
));
if
(
ret
<
0
)
goto
out
;
if
(
ret
==
sizeof
(
buf
))
{
rc
=
-
EOVERFLOW
;
goto
out
;
}
buf
[
ret
]
=
'\0'
;
rc
=
-
EINVAL
;
cmd_start
=
strchr
(
buf
,
'('
);
cmd_end
=
strrchr
(
buf
,
')'
);
if
(
!
cmd_start
||
!
cmd_end
)
goto
out
;
cmd_start
++
;
ppid_start
=
cmd_end
;
for
(
i
=
0
;
i
<
3
;
i
++
)
{
ppid_start
=
strchr
(
ppid_start
,
' '
);
if
(
!
ppid_start
)
goto
out
;
ppid_start
++
;
}
ppid
=
strtoul
(
ppid_start
,
&
end
,
10
);
if
(
end
==
ppid_start
||
*
end
!=
' '
)
goto
out
;
if
(
ppid_r
)
*
ppid_r
=
ppid
;
if
(
cmd_buf
)
{
size_t
len
=
min_t
(
size_t
,
cmd_end
-
cmd_start
,
cmd_buf_sz
-
1
);
memcpy
(
cmd_buf
,
cmd_start
,
len
);
cmd_buf
[
len
]
=
'\0'
;
}
rc
=
0
;
out:
close
(
fd
);
return
rc
;
}
src/mod/endpoints/mod_skypopen/osscuse/ossp-util.h
0 → 100644
浏览文件 @
599a2005
差异被折叠。
点击展开。
src/mod/endpoints/mod_skypopen/osscuse/ossp.c
0 → 100644
浏览文件 @
599a2005
/*
* ossp - OSS Proxy: emulate OSS device using CUSE
*
* Copyright (C) 2008-2010 SUSE Linux Products GmbH
* Copyright (C) 2008-2010 Tejun Heo <tj@kernel.org>
*
* This file is released under the GPLv2.
*/
#include "ossp.h"
const
struct
ossp_arg_size
ossp_arg_sizes
[
OSSP_NR_OPCODES
]
=
{
[
OSSP_MIXER
]
=
{
sizeof
(
struct
ossp_mixer_arg
),
sizeof
(
struct
ossp_mixer_arg
),
0
},
[
OSSP_DSP_OPEN
]
=
{
sizeof
(
struct
ossp_dsp_open_arg
),
0
,
0
},
[
OSSP_DSP_READ
]
=
{
sizeof
(
struct
ossp_dsp_rw_arg
),
0
,
0
},
[
OSSP_DSP_WRITE
]
=
{
sizeof
(
struct
ossp_dsp_rw_arg
),
0
,
0
},
[
OSSP_DSP_POLL
]
=
{
sizeof
(
int
),
sizeof
(
unsigned
),
0
},
[
OSSP_DSP_MMAP
]
=
{
sizeof
(
struct
ossp_dsp_mmap_arg
),
0
,
0
},
[
OSSP_DSP_MUNMAP
]
=
{
sizeof
(
int
),
0
,
0
},
[
OSSP_DSP_RESET
]
=
{
0
,
0
,
0
},
[
OSSP_DSP_SYNC
]
=
{
0
,
0
,
0
},
[
OSSP_DSP_POST
]
=
{
0
,
0
,
0
},
[
OSSP_DSP_GET_RATE
]
=
{
0
,
sizeof
(
int
),
0
},
[
OSSP_DSP_GET_CHANNELS
]
=
{
0
,
sizeof
(
int
),
0
},
[
OSSP_DSP_GET_FORMAT
]
=
{
0
,
sizeof
(
int
),
0
},
[
OSSP_DSP_GET_BLKSIZE
]
=
{
0
,
sizeof
(
int
),
0
},
[
OSSP_DSP_GET_FORMATS
]
=
{
0
,
sizeof
(
int
),
0
},
[
OSSP_DSP_SET_RATE
]
=
{
sizeof
(
int
),
sizeof
(
int
),
0
},
[
OSSP_DSP_SET_CHANNELS
]
=
{
sizeof
(
int
),
sizeof
(
int
),
0
},
[
OSSP_DSP_SET_FORMAT
]
=
{
sizeof
(
int
),
sizeof
(
int
),
0
},
[
OSSP_DSP_SET_SUBDIVISION
]
=
{
sizeof
(
int
),
sizeof
(
int
),
0
},
[
OSSP_DSP_SET_FRAGMENT
]
=
{
sizeof
(
int
),
0
,
0
},
[
OSSP_DSP_GET_TRIGGER
]
=
{
0
,
sizeof
(
int
),
0
},
[
OSSP_DSP_SET_TRIGGER
]
=
{
sizeof
(
int
),
0
,
0
},
[
OSSP_DSP_GET_OSPACE
]
=
{
0
,
sizeof
(
struct
audio_buf_info
),
0
},
[
OSSP_DSP_GET_ISPACE
]
=
{
0
,
sizeof
(
struct
audio_buf_info
),
0
},
[
OSSP_DSP_GET_OPTR
]
=
{
0
,
sizeof
(
struct
count_info
),
0
},
[
OSSP_DSP_GET_IPTR
]
=
{
0
,
sizeof
(
struct
count_info
),
0
},
[
OSSP_DSP_GET_ODELAY
]
=
{
0
,
sizeof
(
int
),
0
},
};
const
char
*
ossp_cmd_str
[
OSSP_NR_OPCODES
]
=
{
[
OSSP_MIXER
]
=
"MIXER"
,
[
OSSP_DSP_OPEN
]
=
"OPEN"
,
[
OSSP_DSP_READ
]
=
"READ"
,
[
OSSP_DSP_WRITE
]
=
"WRITE"
,
[
OSSP_DSP_POLL
]
=
"POLL"
,
[
OSSP_DSP_MMAP
]
=
"MMAP"
,
[
OSSP_DSP_MUNMAP
]
=
"MUNMAP"
,
[
OSSP_DSP_RESET
]
=
"RESET"
,
[
OSSP_DSP_SYNC
]
=
"SYNC"
,
[
OSSP_DSP_POST
]
=
"POST"
,
[
OSSP_DSP_GET_RATE
]
=
"GET_RATE"
,
[
OSSP_DSP_GET_CHANNELS
]
=
"GET_CHANNELS"
,
[
OSSP_DSP_GET_FORMAT
]
=
"GET_FORMAT"
,
[
OSSP_DSP_GET_BLKSIZE
]
=
"GET_BLKSIZE"
,
[
OSSP_DSP_GET_FORMATS
]
=
"GET_FORMATS"
,
[
OSSP_DSP_SET_RATE
]
=
"SET_RATE"
,
[
OSSP_DSP_SET_CHANNELS
]
=
"SET_CHANNELS"
,
[
OSSP_DSP_SET_FORMAT
]
=
"SET_FORMAT"
,
[
OSSP_DSP_SET_SUBDIVISION
]
=
"SET_BUSDIVISION"
,
[
OSSP_DSP_SET_FRAGMENT
]
=
"SET_FRAGMENT"
,
[
OSSP_DSP_GET_TRIGGER
]
=
"GET_TRIGGER"
,
[
OSSP_DSP_SET_TRIGGER
]
=
"SET_TRIGGER"
,
[
OSSP_DSP_GET_OSPACE
]
=
"GET_OSPACE"
,
[
OSSP_DSP_GET_ISPACE
]
=
"GET_ISPACE"
,
[
OSSP_DSP_GET_OPTR
]
=
"GET_OPTR"
,
[
OSSP_DSP_GET_IPTR
]
=
"GET_IPTR"
,
[
OSSP_DSP_GET_ODELAY
]
=
"GET_ODELAY"
,
};
const
char
*
ossp_notify_str
[
OSSP_NR_NOTIFY_OPCODES
]
=
{
[
OSSP_NOTIFY_POLL
]
=
"POLL"
,
[
OSSP_NOTIFY_OBITUARY
]
=
"OBITUARY"
,
[
OSSP_NOTIFY_VOLCHG
]
=
"VOLCHG"
,
};
src/mod/endpoints/mod_skypopen/osscuse/ossp.h
0 → 100644
浏览文件 @
599a2005
/*
* ossp - OSS Proxy: emulate OSS device using CUSE
*
* Copyright (C) 2008-2010 SUSE Linux Products GmbH
* Copyright (C) 2008-2010 Tejun Heo <tj@kernel.org>
*
* This file is released under the GPLv2.
*/
#ifndef _OSSP_H
#define _OSSP_H
#include <sys/types.h>
#include <inttypes.h>
#include <sys/soundcard.h>
#define OSSP_VERSION "1.3.2"
#define OSSP_CMD_MAGIC 0xdeadbeef
#define OSSP_REPLY_MAGIC 0xbeefdead
#define OSSP_NOTIFY_MAGIC 0xbebebebe
#define PLAY 0
#define REC 1
#define LEFT 0
#define RIGHT 1
enum
ossp_opcode
{
OSSP_MIXER
,
OSSP_DSP_OPEN
,
OSSP_DSP_READ
,
OSSP_DSP_WRITE
,
OSSP_DSP_POLL
,
OSSP_DSP_MMAP
,
OSSP_DSP_MUNMAP
,
OSSP_DSP_RESET
,
OSSP_DSP_SYNC
,
OSSP_DSP_POST
,
OSSP_DSP_GET_RATE
,
OSSP_DSP_GET_CHANNELS
,
OSSP_DSP_GET_FORMAT
,
OSSP_DSP_GET_BLKSIZE
,
OSSP_DSP_GET_FORMATS
,
OSSP_DSP_SET_RATE
,
OSSP_DSP_SET_CHANNELS
,
OSSP_DSP_SET_FORMAT
,
OSSP_DSP_SET_SUBDIVISION
,
OSSP_DSP_SET_FRAGMENT
,
OSSP_DSP_GET_TRIGGER
,
OSSP_DSP_SET_TRIGGER
,
OSSP_DSP_GET_OSPACE
,
OSSP_DSP_GET_ISPACE
,
OSSP_DSP_GET_OPTR
,
OSSP_DSP_GET_IPTR
,
OSSP_DSP_GET_ODELAY
,
OSSP_NR_OPCODES
,
};
enum
ossp_notify_opcode
{
OSSP_NOTIFY_POLL
,
OSSP_NOTIFY_OBITUARY
,
OSSP_NOTIFY_VOLCHG
,
OSSP_NR_NOTIFY_OPCODES
,
};
struct
ossp_mixer_arg
{
int
vol
[
2
][
2
];
};
struct
ossp_dsp_open_arg
{
int
flags
;
pid_t
opener_pid
;
};
struct
ossp_dsp_rw_arg
{
unsigned
nonblock
:
1
;
};
struct
ossp_dsp_mmap_arg
{
int
dir
;
size_t
size
;
};
struct
ossp_cmd
{
unsigned
magic
;
enum
ossp_opcode
opcode
;
size_t
din_size
;
size_t
dout_size
;
};
struct
ossp_reply
{
unsigned
magic
;
int
result
;
size_t
dout_size
;
/* <= cmd.data_in_size */
};
struct
ossp_notify
{
unsigned
magic
;
enum
ossp_notify_opcode
opcode
;
};
struct
ossp_arg_size
{
ssize_t
carg_size
;
ssize_t
rarg_size
;
unsigned
has_fd
:
1
;
};
extern
const
struct
ossp_arg_size
ossp_arg_sizes
[
OSSP_NR_OPCODES
];
extern
const
char
*
ossp_cmd_str
[
OSSP_NR_OPCODES
];
extern
const
char
*
ossp_notify_str
[
OSSP_NR_NOTIFY_OPCODES
];
#endif
/* _OSSP_H */
src/mod/endpoints/mod_skypopen/osscuse/osspd.c
0 → 100644
浏览文件 @
599a2005
差异被折叠。
点击展开。
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论