Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
577d7b55
提交
577d7b55
authored
12月 11, 2010
作者:
Giovanni Maruzzelli
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
skypopen: added a proof of concept standalone OSS audio driver (for Skype-oss clients)
上级
009c41d4
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
584 行增加
和
0 行删除
+584
-0
Makefile
src/mod/endpoints/mod_skypopen/oss/Makefile
+43
-0
main.c
src/mod/endpoints/mod_skypopen/oss/main.c
+335
-0
scull.h
src/mod/endpoints/mod_skypopen/oss/scull.h
+64
-0
scull.init
src/mod/endpoints/mod_skypopen/oss/scull.init
+142
-0
没有找到文件。
src/mod/endpoints/mod_skypopen/oss/Makefile
0 → 100644
浏览文件 @
577d7b55
# Comment/uncomment the following line to disable/enable debugging
#DEBUG = y
LDDINC
=
/usr/src/linux-headers-2.6.32-26-server/include
# Add your debugging flag (or not) to CFLAGS
ifeq
($(DEBUG),y)
DEBFLAGS
=
-O
-g
-DSCULL_DEBUG
# "-O" is needed to expand inlines
else
DEBFLAGS
=
-O2
-Wall
endif
EXTRA_CFLAGS
+=
$(DEBFLAGS)
EXTRA_CFLAGS
+=
-I
$(LDDINC)
ifneq
($(KERNELRELEASE),)
# call from kernel build system
scull-objs
:=
main.o
obj-m
:=
scull.o
else
KERNELDIR
?=
/lib/modules/
$(
shell
uname
-r
)
/build
PWD
:=
$(
shell
pwd
)
modules
:
$(MAKE)
-C
$(KERNELDIR)
M
=
$(PWD)
LDDINC
=
$(PWD)
/../include modules
endif
clean
:
rm
-rf
*
.o
*
~ core .depend .
*
.cmd
*
.ko
*
.mod.c .tmp_versions
depend .depend dep
:
$(CC)
$(EXTRA_CFLAGS)
-M
*
.c
>
.depend
ifeq
(.depend,$(wildcard
.depend))
include
.depend
endif
src/mod/endpoints/mod_skypopen/oss/main.c
0 → 100644
浏览文件 @
577d7b55
/*
* main.c -- the bare scull char module
*
* Copyright (C) 2010 Giovanni Maruzzelli
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2001 O'Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* should list that the code comes from the book "Linux Device
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
* by O'Reilly & Associates. No warranty is attached;
* we cannot take responsibility for errors or fitness for use.
*
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
/* printk() */
#include <linux/slab.h>
/* kmalloc() */
#include <linux/fs.h>
/* everything... */
#include <linux/errno.h>
/* error codes */
#include <linux/types.h>
/* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
/* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <asm/system.h>
/* cli(), *_flags */
#include <asm/uaccess.h>
/* copy_*_user */
#include <linux/soundcard.h>
#include <linux/delay.h>
#include <linux/hrtimer.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/jiffies.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include "scull.h"
/* local definitions */
/*
* Our parameters which can be set at load time.
*/
int
scull_major
=
SCULL_MAJOR
;
int
scull_minor
=
3
;
int
scull_nr_devs
=
SCULL_NR_DEVS
;
/* number of bare scull devices */
module_param
(
scull_major
,
int
,
S_IRUGO
);
module_param
(
scull_minor
,
int
,
S_IRUGO
);
module_param
(
scull_nr_devs
,
int
,
S_IRUGO
);
MODULE_AUTHOR
(
"Original: Alessandro Rubini, Jonathan Corbet. Heavy modified by: Giovanni Maruzzelli"
);
MODULE_LICENSE
(
"Dual BSD/GPL"
);
static
struct
scull_dev
*
scull_devices
;
/* allocated in scull_init_module */
#define GIOVA_BLK 3840
#define GIOVA_SLEEP 40000
void
my_timer_callback_inq
(
unsigned
long
data
)
{
struct
scull_dev
*
dev
=
(
void
*
)
data
;
wake_up_interruptible
(
&
dev
->
inq
);
mod_timer
(
&
dev
->
timer_inq
,
jiffies
+
msecs_to_jiffies
(
GIOVA_SLEEP
/
1000
)
);
}
void
my_timer_callback_outq
(
unsigned
long
data
)
{
struct
scull_dev
*
dev
=
(
void
*
)
data
;
wake_up_interruptible
(
&
dev
->
outq
);
mod_timer
(
&
dev
->
timer_outq
,
jiffies
+
msecs_to_jiffies
(
GIOVA_SLEEP
/
1000
)
);
}
/* The clone-specific data structure includes a key field */
struct
scull_listitem
{
struct
scull_dev
device
;
dev_t
key
;
struct
list_head
list
;
};
/* The list of devices, and a lock to protect it */
static
LIST_HEAD
(
scull_c_list
);
static
spinlock_t
scull_c_lock
=
SPIN_LOCK_UNLOCKED
;
/* Look for a device or create one if missing */
static
struct
scull_dev
*
scull_c_lookfor_device
(
dev_t
key
)
{
struct
scull_listitem
*
lptr
;
list_for_each_entry
(
lptr
,
&
scull_c_list
,
list
)
{
if
(
lptr
->
key
==
key
)
return
&
(
lptr
->
device
);
}
/* not found */
lptr
=
kmalloc
(
sizeof
(
struct
scull_listitem
),
GFP_KERNEL
);
if
(
!
lptr
)
return
NULL
;
/* initialize the device */
memset
(
lptr
,
0
,
sizeof
(
struct
scull_listitem
));
lptr
->
key
=
key
;
init_waitqueue_head
(
&
lptr
->
device
.
inq
);
init_waitqueue_head
(
&
lptr
->
device
.
outq
);
printk
(
" Timer installing
\n
"
);
setup_timer
(
&
lptr
->
device
.
timer_inq
,
my_timer_callback_inq
,
(
long
int
)
lptr
);
setup_timer
(
&
lptr
->
device
.
timer_outq
,
my_timer_callback_outq
,
(
long
int
)
lptr
);
printk
(
"Starting timer to fire in %dms (%ld)
\n
"
,
GIOVA_SLEEP
/
1000
,
jiffies
);
mod_timer
(
&
lptr
->
device
.
timer_inq
,
jiffies
+
msecs_to_jiffies
(
GIOVA_SLEEP
/
1000
)
);
mod_timer
(
&
lptr
->
device
.
timer_outq
,
jiffies
+
msecs_to_jiffies
(
GIOVA_SLEEP
/
1000
)
);
/* place it in the list */
list_add
(
&
lptr
->
list
,
&
scull_c_list
);
return
&
(
lptr
->
device
);
}
static
int
scull_c_open
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
struct
scull_dev
*
dev
;
dev_t
key
;
if
(
!
current
->
pid
)
{
printk
(
"Process
\"
%s
\"
has no pid
\n
"
,
current
->
comm
);
return
-
EINVAL
;
}
key
=
current
->
pid
;
/* look for a scullc device in the list */
spin_lock
(
&
scull_c_lock
);
dev
=
scull_c_lookfor_device
(
key
);
spin_unlock
(
&
scull_c_lock
);
if
(
!
dev
)
return
-
ENOMEM
;
/* then, everything else is copied from the bare scull device */
filp
->
private_data
=
dev
;
return
0
;
/* success */
}
static
int
scull_c_release
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
/*
* Nothing to do, because the device is persistent.
* A `real' cloned device should be freed on last close
*/
return
0
;
}
/*************************************************************/
/*
* Open and close
*/
ssize_t
scull_read
(
struct
file
*
filp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
f_pos
)
{
struct
scull_dev
*
dev
=
filp
->
private_data
;
DEFINE_WAIT
(
wait
);
prepare_to_wait
(
&
dev
->
inq
,
&
wait
,
TASK_INTERRUPTIBLE
);
schedule
();
finish_wait
(
&
dev
->
inq
,
&
wait
);
return
count
;
}
ssize_t
scull_write
(
struct
file
*
filp
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
f_pos
)
{
struct
scull_dev
*
dev
=
filp
->
private_data
;
DEFINE_WAIT
(
wait
);
prepare_to_wait
(
&
dev
->
outq
,
&
wait
,
TASK_INTERRUPTIBLE
);
schedule
();
finish_wait
(
&
dev
->
outq
,
&
wait
);
return
count
;
}
/*
* The ioctl() implementation
*/
int
scull_ioctl
(
struct
inode
*
inode
,
struct
file
*
filp
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
void
__user
*
argp
=
(
void
__user
*
)
arg
;
int
__user
*
p
=
argp
;
switch
(
cmd
)
{
case
OSS_GETVERSION
:
return
put_user
(
SOUND_VERSION
,
p
);
case
SNDCTL_DSP_GETBLKSIZE
:
return
put_user
(
GIOVA_BLK
,
p
);
case
SNDCTL_DSP_GETFMTS
:
return
put_user
(
28731
,
p
);
default:
return
0
;
}
}
struct
file_operations
scull_fops
=
{
.
owner
=
THIS_MODULE
,
.
llseek
=
no_llseek
,
.
read
=
scull_read
,
.
write
=
scull_write
,
.
ioctl
=
scull_ioctl
,
.
open
=
scull_c_open
,
.
release
=
scull_c_release
,
};
/*
* Finally, the module stuff
*/
/*
* The cleanup function is used to handle initialization failures as well.
* Thefore, it must be careful to work correctly even if some of the items
* have not been initialized
*/
void
scull_cleanup_module
(
void
)
{
int
i
;
int
ret
;
struct
scull_listitem
*
lptr
,
*
next
;
dev_t
devno
=
MKDEV
(
scull_major
,
scull_minor
);
/* Get rid of our char dev entries */
if
(
scull_devices
)
{
for
(
i
=
0
;
i
<
scull_nr_devs
;
i
++
)
{
cdev_del
(
&
scull_devices
[
i
].
cdev
);
}
kfree
(
scull_devices
);
}
/* And all the cloned devices */
list_for_each_entry_safe
(
lptr
,
next
,
&
scull_c_list
,
list
)
{
ret
=
del_timer
(
&
lptr
->
device
.
timer_inq
);
if
(
ret
)
printk
(
"The inq timer was still in use...
\n
"
);
ret
=
del_timer
(
&
lptr
->
device
.
timer_outq
);
if
(
ret
)
printk
(
"The outq timer was still in use...
\n
"
);
list_del
(
&
lptr
->
list
);
kfree
(
lptr
);
}
printk
(
"Timer uninstalling
\n
"
);
/* cleanup_module is never called if registering failed */
unregister_chrdev_region
(
devno
,
scull_nr_devs
);
}
/*
* Set up the char_dev structure for this device.
*/
static
void
scull_setup_cdev
(
struct
scull_dev
*
dev
,
int
index
)
{
int
err
,
devno
=
MKDEV
(
scull_major
,
scull_minor
+
index
);
cdev_init
(
&
dev
->
cdev
,
&
scull_fops
);
dev
->
cdev
.
owner
=
THIS_MODULE
;
dev
->
cdev
.
ops
=
&
scull_fops
;
err
=
cdev_add
(
&
dev
->
cdev
,
devno
,
1
);
/* Fail gracefully if need be */
if
(
err
)
printk
(
KERN_NOTICE
"Error %d adding scull%d"
,
err
,
index
);
}
int
scull_init_module
(
void
)
{
int
result
,
i
;
dev_t
dev
=
0
;
/*
* Get a range of minor numbers to work with, asking for a dynamic
* major unless directed otherwise at load time.
*/
if
(
scull_major
)
{
dev
=
MKDEV
(
scull_major
,
scull_minor
);
result
=
register_chrdev_region
(
dev
,
scull_nr_devs
,
"dsp"
);
}
else
{
result
=
alloc_chrdev_region
(
&
dev
,
scull_minor
,
scull_nr_devs
,
"dsp"
);
scull_major
=
MAJOR
(
dev
);
}
if
(
result
<
0
)
{
printk
(
KERN_WARNING
"scull: can't get major %d
\n
"
,
scull_major
);
return
result
;
}
/*
* allocate the devices -- we can't have them static, as the number
* can be specified at load time
*/
scull_devices
=
kmalloc
(
scull_nr_devs
*
sizeof
(
struct
scull_dev
),
GFP_KERNEL
);
if
(
!
scull_devices
)
{
result
=
-
ENOMEM
;
goto
fail
;
/* Make this more graceful */
}
memset
(
scull_devices
,
0
,
scull_nr_devs
*
sizeof
(
struct
scull_dev
));
/* Initialize each device. */
for
(
i
=
0
;
i
<
scull_nr_devs
;
i
++
)
{
scull_setup_cdev
(
&
scull_devices
[
i
],
i
);
}
/* At this point call the init function for any friend device */
dev
=
MKDEV
(
scull_major
,
scull_minor
+
scull_nr_devs
);
return
0
;
/* succeed */
fail:
scull_cleanup_module
();
return
result
;
}
module_init
(
scull_init_module
);
module_exit
(
scull_cleanup_module
);
src/mod/endpoints/mod_skypopen/oss/scull.h
0 → 100644
浏览文件 @
577d7b55
/*
* scull.h -- definitions for the char module
*
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2001 O'Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* should list that the code comes from the book "Linux Device
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
* by O'Reilly & Associates. No warranty is attached;
* we cannot take responsibility for errors or fitness for use.
*
* $Id: scull.h,v 1.15 2004/11/04 17:51:18 rubini Exp $
*/
#ifndef _SCULL_H_
#define _SCULL_H_
#include <linux/ioctl.h>
/* needed for the _IOW etc stuff used later */
#ifndef SCULL_MAJOR
#define SCULL_MAJOR 14
/* dynamic major by default */
#endif
#ifndef SCULL_NR_DEVS
#define SCULL_NR_DEVS 1
/* scull0 through scull3 */
#endif
struct
scull_dev
{
struct
cdev
cdev
;
/* Char device structure */
wait_queue_head_t
inq
;
/* read and write queues */
wait_queue_head_t
outq
;
/* read and write queues */
struct
timer_list
timer_inq
;
struct
timer_list
timer_outq
;
//unsigned long read_howmany;
//unsigned long write_howmany;
//unsigned long read_sleeped_acc;
//unsigned long write_sleeped_acc;
//double read_delay; /* how much delay last time */
//double write_delay; /* how much delay last time */
};
/*
* The different configurable parameters
*/
extern
int
scull_major
;
/* main.c */
extern
int
scull_nr_devs
;
/*
* Prototypes for shared functions
*/
ssize_t
scull_read
(
struct
file
*
filp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
f_pos
);
ssize_t
scull_write
(
struct
file
*
filp
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
f_pos
);
int
scull_ioctl
(
struct
inode
*
inode
,
struct
file
*
filp
,
unsigned
int
cmd
,
unsigned
long
arg
);
#endif
/* _SCULL_H_ */
src/mod/endpoints/mod_skypopen/oss/scull.init
0 → 100644
浏览文件 @
577d7b55
#!/bin/bash
# Sample init script for the a driver module <rubini@linux.it>
DEVICE
=
"scull"
SECTION
=
"misc"
# The list of filenames and minor numbers: $PREFIX is prefixed to all names
PREFIX
=
"scull"
FILES
=
" 0 0 1 1 2 2 3 3 priv 16
pipe0 32 pipe1 33 pipe2 34 pipe3 35
single 48 uid 64 wuid 80"
INSMOD
=
/sbin/insmod
;
# use /sbin/modprobe if you prefer
function
device_specific_post_load
()
{
true
;
# fill at will
}
function
device_specific_pre_unload
()
{
true
;
# fill at will
}
# Everything below this line should work unchanged for any char device.
# Obviously, however, no options on the command line: either in
# /etc/${DEVICE}.conf or /etc/modules.conf (if modprobe is used)
# Optional configuration file: format is
# owner <ownername>
# group <groupname>
# mode <modename>
# options <insmod options>
CFG
=
/etc/
${
DEVICE
}
.conf
# kernel version, used to look for modules
KERNEL
=
`
uname
-r
`
#FIXME: it looks like there is no misc section. Where should it be?
MODDIR
=
"/lib/modules/
${
KERNEL
}
/kernel/drivers/
${
SECTION
}
"
if
[
!
-d
$MODDIR
]
;
then
MODDIR
=
"/lib/modules/
${
KERNEL
}
/
${
SECTION
}
"
;
fi
# Root or die
if
[
"
$(
id
-u
)
"
!=
"0"
]
then
echo
"You must be root to load or unload kernel modules"
exit
1
fi
# Read configuration file
if
[
-r
$CFG
]
;
then
OWNER
=
`
awk
"
\\
$1
==
\"
owner
\"
{print
\\
$2
}"
$CFG
`
GROUP
=
`
awk
"
\\
$1
==
\"
group
\"
{print
\\
$2
}"
$CFG
`
MODE
=
`
awk
"
\\
$1
==
\"
mode
\"
{print
\\
$2
}"
$CFG
`
# The options string may include extra blanks or only blanks
OPTIONS
=
`
sed
-n
'/^options / s/options //p'
$CFG
`
fi
# Create device files
function
create_files
()
{
cd
/dev
local
devlist
=
""
local
file
while
true
;
do
if
[
$#
-lt
2
]
;
then
break
;
fi
file
=
"
${
DEVICE
}
$1
"
mknod
$file
c
$MAJOR
$2
devlist
=
"
$devlist
$file
"
shift
2
done
if
[
-n
"
$OWNER
"
]
;
then
chown
$OWNER
$devlist
;
fi
if
[
-n
"
$GROUP
"
]
;
then
chgrp
$GROUP
$devlist
;
fi
if
[
-n
"
$MODE
"
]
;
then
chmod
$MODE
$devlist
;
fi
}
# Remove device files
function
remove_files
()
{
cd
/dev
local
devlist
=
""
local
file
while
true
;
do
if
[
$#
-lt
2
]
;
then
break
;
fi
file
=
"
${
DEVICE
}
$1
"
devlist
=
"
$devlist
$file
"
shift
2
done
rm
-f
$devlist
}
# Load and create files
function
load_device
()
{
if
[
-f
$MODDIR
/
$DEVICE
.o
]
;
then
devpath
=
$MODDIR
/
$DEVICE
.o
else if
[
-f
./
$DEVICE
.o
]
;
then
devpath
=
./
$DEVICE
.o
else
devpath
=
$DEVICE
;
# let insmod/modprobe guess
fi
;
fi
if
[
"
$devpath
"
!=
"
$DEVICE
"
]
;
then
echo
-n
" (loading file
$devpath
)"
fi
if
$INSMOD
$devpath
$OPTIONS
;
then
MAJOR
=
`
awk
"
\\
$2
==
\"
$DEVICE
\"
{print
\\
$1
}"
/proc/devices
`
remove_files
$FILES
create_files
$FILES
device_specific_post_load
else
echo
" FAILED!"
fi
}
# Unload and remove files
function
unload_device
()
{
device_specific_pre_unload
/sbin/rmmod
$DEVICE
remove_files
$FILES
}
case
"
$1
"
in
start
)
echo
-n
"Loading
$DEVICE
"
load_device
echo
"."
;;
stop
)
echo
-n
"Unloading
$DEVICE
"
unload_device
echo
"."
;;
force-reload|restart
)
echo
-n
"Reloading
$DEVICE
"
unload_device
load_device
echo
"."
;;
*
)
echo
"Usage:
$0
{start|stop|restart|force-reload}"
exit
1
esac
exit
0
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论