2011-07-27 10 views
5

리눅스 시스템에서 오디오 재생 및 캡처를 위해 사용할 가상 사운드 카드 드라이버를 작성하고 싶습니다. 드라이버는 오디오 데이터 읽기/쓰기 용 버퍼를 사용해야합니다. 나는 다음과 같은 기본 드라이버를 작성했습니다 :리눅스에 사운드 카드 드라이버 등록하기

#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은 리눅스의 오래된 OSS 사운드 시스템에서 사용되는 사운드 카드에 사용 된 디바이스 노드 였지만 요즘은 새로운 ALSA 사운드 시스템을 기반으로하는 디바이스를 찾는 것이 거의 불가능합니다.

일부 소프트웨어는 여전히 OSS를 지원하지만 특별한 옵션을 제공하거나 구성을 변경하여 ALSA 대신 OSS를 사용하도록 지시해야 할 수도 있습니다.

ALSA 장치는 /dev/snd에서 찾을 수 있으며 일반적으로 이전 OSS 장치보다 복잡하기 때문에 직접 액세스 할 수 없습니다. 대신 일반적으로 libasound이 상호 작용하는 데 사용됩니다.

+2

답장을 보내 주셔서 감사합니다. 사실 나는 ALSA에서 장치 드라이버를 작성하기위한 안내서를 읽었습니다. 그러나이 드라이버는 ALSA에 연결되어야하고 ** libasound를 사용하지 않고 ** 시스템에서 드라이버 **에 직접 액세스 할 수 없습니다. 직접 액세스 할 수있는 ALSA API를 사용하여 가상 드라이버를 작성할 수있는 방법이 있습니까? – Khaled

+0

그러나 Linux 장치 드라이버 (누가 하드웨어와 대화했는지)를 작성하면이를 alsa에 적용해야합니까? Alsa가 내 가짜 사운드 카드를 확인하고 함께 작업해야합니까? – deFreitas

관련 문제