2011-07-27 20 views
5

Ses çalma ve yakalama için linux sistemi tarafından kullanılacak sanal bir ses kartı sürücüsü yazmak istiyorum. Sürücü, ses verileri okuma/yazma için bir arabellek kullanmalıdır. Ben aşağıdaki temel sürücüyü yazdım:Linux'ta bir ses kartı sürücüsü kaydetme

#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 Bu modülü ing /dev/dsp bir sürücü oluşturur. Ayrıca, /sys/devices/virtual/sound/dsp/'da bulunur, dolayısıyla sistem tarafından sanal bir ses sürücüsü olarak tanınır.

Bu cihazı, oynatma ve uygulamalardan yakalama için henüz seçemiyorum. Bu sürücüyü ses uygulamaları tarafından numaralandırılmak için başka ne yapmam gerekiyor?

+0

Bu, bir çekirdek sürücü tarafından sahte bir donanım uygular alsa veya OSS bağımsız ve mümkün olmalıdır düşünüyorum. Alsa'ya uygular benim için mantıklı değil. Ben de bunu nasıl yapacağımı bilmiyorum. – deFreitas

cevap

1

Eh /dev/dsp, linux'daki eski OSS ses sisteminin altında bir ses kartı için kullanılan aygıt düğümüydi, ancak bu günlerde her şey hemen hemen her zaman ALSA ses sistemine dayalı aygıtları aramaya varsayılan olacak.

Bazı yazılımlar hala OSS'yi desteklemektedir, ancak ALSA yerine OSS'yi kullanmasını söylemek için özel seçenekler vermeniz veya yapılandırmayı değiştirmeniz gerekebilir.

ALSA aygıtları /dev/snd altında bulunur ve normal olarak doğrudan erişilmez, çünkü eski OSS aygıtlarından daha karmaşıktır. Bunun yerine, libasound normalde onlarla etkileşimde bulunmak için kullanılır.

+2

Cevabınız için teşekkür ederiz. Aslında ALSA’da aygıt sürücüsü yazım kılavuzunu okudum. Ancak bu sürücü ALSA'ya takılacak ve sürücüye ** doğrudan "libasound" kullanmadan sisteme erişemiyorum. Doğrudan erişilebilen ALSA API kullanarak sanal sürücü yazmanın bir yolu var mı? – Khaled

+0

Ama bir Linux aygıt sürücüsü (donanım ile kiminle konuşur) yazarsam, bunu alsa'ya uyarlamam gerekir. Alsa, sahte ses kartımı tanımlamak ve onunla çalışmak zorunda değil mi? – deFreitas