2011-07-27 29 views
5

我想編寫一個虛擬聲卡驅動程序,該驅動程序將被Linux系統用於音頻播放和捕獲。驅動程序應使用緩衝區來讀取/寫入音頻數據。我寫了下面的基本驅動程序:在Linux中註冊聲卡驅動程序

#include <linux/module.h> 
#include <linux/kernel.h> 
#include <linux/sound.h> 

#include <linux/sysctl.h> 
#include <linux/device.h> 

#include <linux/slab.h> /* kmalloc() */ 
#include <linux/gfp.h> 
#include <asm/uaccess.h> /* copy_from/to_user */ 
#include <linux/major.h> 
#include <linux/fs.h> 
#include <linux/pci.h> 
#include <linux/err.h> 

#include <sound/core.h> 

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/中找到,所以它被系統識別爲虛擬音頻驅動程序。

我還沒有能夠選擇此設備來播放和從應用程序捕獲。我還需要做些什麼來使音頻應用程序列舉此驅動程序?

+0

我認爲通過內核驅動程序實現假硬件應該是可能的並且獨立於alsa或OSS。對alsa的實現對我來說沒有意義。我也不知道該怎麼做。 – deFreitas

回答

1

好吧/dev/dsp是linux下舊OSS聲音系統下聲卡的設備節點,但是現在幾乎所有的東西都會默認尋找基於新ALSA聲音系統的設備。

某些軟件仍然支持OSS,但您可能需要給它特殊選項或更改配置,以告訴它使用OSS而不是ALSA。

ALSA設備位於/dev/snd下,通常不會直接訪問,因爲它們比舊的OSS設備更復雜。相反,libasound通常用於與它們進行交互。

+2

感謝您的回覆。其實我已經閱讀了在ALSA中編寫設備驅動程序的指南。但是這個驅動程序應該插入到ALSA中,並且我不能直接從系統訪問驅動程序**而不使用libasound。 有沒有什麼辦法可以直接使用ALSA API編寫虛擬驅動? – Khaled

+0

但是,如果我寫一個Linux設備驅動程序(誰正在與硬件交談),那麼我需要適應它alsa? Alsa是否需要識別我的假聲卡並使用它? – deFreitas