我想编写一个虚拟声卡驱动程序,该驱动程序将被Linux系统用于音频播放和捕获。驱动程序应使用缓冲区来读取/写入音频数据。我写了下面的基本驱动程序:在Linux中注册声卡驱动程序
#include
#include
#include
#include
#include
#include /* kmalloc() */
#include
#include /* copy_from/to_user */
#include
#include
#include
#include
#include
static char* mod_name = "prosip";
MODULE_LICENSE("GPL");
MODULE_VERSION("0.0.1111");
MODULE_AUTHOR("DD-DDD");
MODULE_DESCRIPTION("proSip Virtual Sound Card");
//
static int ver_major = 133;
static int ver_minor = 3;
//
static int buffer_size = 0;
static char* buffer;
static int read_count = 0;
/* Declaration of memory.c functions */
int prosip_open(struct inode *inode, struct file *filp);
int prosip_release(struct inode *inode, struct file *filp);
//
ssize_t prosip_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
ssize_t prosip_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos);
//
int prosip_ioctl(struct inode *inode,struct file *file,unsigned int ioctl_num,unsigned long ioctl_param);
//
static int __init prosip_init(void);
static void __exit prosip_exit(void);
/* Structure that declares the usual file access functions */
struct file_operations sound_fops =
{
owner:
THIS_MODULE,
read:
prosip_read,
write:
prosip_write,
open:
prosip_open,
release:
prosip_release,
ioctl:
prosip_ioctl
};
/* Declaration of the init and exit functions */
module_init(prosip_init);
module_exit(prosip_exit);
static int __init prosip_init(void)
{
int ret = -1;
buffer_size = 0;
printk("<1>[prosip] Init...!\n");
ret = register_sound_dsp(&sound_fops, ver_minor);
if(ret < 0)
{
printk("<1> [prosip] Registration failure\n");
//
return ret;
}
else
{
ver_minor = ret;
//
printk("<1> [prosip] DSP Registered succesfully with id %d\n", ret);
}
buffer = kmalloc(101, GFP_KERNEL);
if(buffer == 0)
{
printk("<1>[prosip] Failed to allocate buffer !!!\n");
//
return -ENOMEM;
}
//
return 0;
}
static void __exit prosip_exit(void)
{
printk("<1> [prosip] Sound Exit...\n");
unregister_sound_special(ver_minor);
if(buffer)
{
kfree(buffer);
}
}
/* Declaration of memory.c functions */
int prosip_open(struct inode *inode, struct file *filp)
{
printk("<1> [prosip] Sound Open... \n");
try_module_get(THIS_MODULE);
return 0;
}
//
int prosip_release(struct inode *inode, struct file *filp)
{
printk("<1> [MySound] Sound Release... \n");
module_put(THIS_MODULE);
return 0;
}
//
ssize_t prosip_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
printk("<1> [prosip] Sound read...\n");
printk("<1> [prosip] Writing Count: %d\n", count);
if(buffer == 0)
{
printk("<1> NULL buffer!!! Unable to read");
return 0;
}
//
count = buffer_size;
if(read_count == 0)
{
read_count = buffer_size;
}
else
{
read_count = 0;
}
copy_to_user(buf, buffer, buffer_size);
printk("<1> [prosip] Buffer: %s, buf: %s, Count: %d\n", buffer, buf, count);
return read_count;
}
//
ssize_t prosip_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
printk("<1> [prosip] Sound write...!\n");
printk("<1> [prosip] Writing Count: %d\n", count);
//
if(buffer == 0)
{
printk("<1> NULL buffer!!! Unable to write");
return 0;
}
copy_from_user(buffer, buf, count);
buffer[count] = 0;
buffer_size = count;
printk("<1> [MySound] Writing Buffer: %s, Count: %d\n", buffer, count);
return count;
}
/*
* This function is called whenever a process tries to do an ioctl on our
* device file.
*
*/
int prosip_ioctl(struct inode *inode,
struct file *file,
unsigned int ioctl_num,
unsigned long ioctl_param)
{
//
return 0;
}
insmod荷兰国际集团这个模块创建在/dev/dsp驱动程序。它也可以在/sys/devices/virtual/sound/dsp/中找到,所以它被系统识别为虚拟音频驱动程序。
我还没有能够选择此设备来播放和从应用程序捕获。我还需要做些什么来使音频应用程序列举此驱动程序?
2011-07-27
Khaled
+0
我认为通过内核驱动程序实现假硬件应该是可能的并且独立于alsa或OSS。对alsa的实现对我来说没有意义。我也不知道该怎么做。 –