- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试使用 ALSA 创建我自己的自定义声音驱动程序。到目前为止,我已经成功加载了模块,我的意思是:
我通过放置在这些函数中的转储发现了这一点。
但是当我尝试在我的应用程序中使用 snd_pcm_open() 函数连接到我的驱动程序时,我没有看到我在 .open() 函数中添加的转储存储在 struct snd_pcm_ops 中。因此,出于某种原因,我的驱动程序未从我的应用程序中看到。
我加载了原始驱动程序并执行了相同的应用程序,它工作正常。
你知道为什么我的驱动程序不能从用户空间访问吗?
谢谢。
代码如下:
#include <linux/fs.h>
#include <linux/module.h> // MOD_DEVICE_TABLE,
#include <linux/init.h>
#include <linux/pci.h> // pci_device_id,
#include <linux/interrupt.h>
#include <linux/version.h> // KERNEL_VERSION,
#include <iso646.h>
#include <linux/kobject.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/uaccess.h> // copy_to_user,
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <linux/time.h>
MODULE_LICENSE("GPL");
// vendor and device id of the PCI device
#define VENDOR_ID 0x8086
#define DEVICE_ID 0x2415
/*************** DATA **********************/
/* module parameters (see "Module Parameters") */
/* SNDRV_CARDS: maximum number of cards supported by this module */
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
#define BARS 6
enum bars{bar0=0, bar1=1, bar2=2, bar3=3, bar4=4, bar5=5};
#define IOREG_0 0
#define IOREG_1 1
/*OFFSETS TO REGISTER*/
#define GLOBAL_STATUS_REGISTER_OFFSET 0x30
struct mem_regions
{
unsigned int start_addr;
unsigned int end_addr;
unsigned int mem_len;
unsigned int bar;
unsigned int flag;
void __iomem *mem_mapped_addr;
};
struct mychip {
struct snd_card *card;
struct pci_dev *pci;
unsigned long port;
int irq;
struct mem_regions memregs[6];
struct snd_pcm *pcm;
struct snd_pcm_substream *substream;
};
/*******************************************/
/******************** FUNCTION PROTOTYPES *********************************/
static int __devinit snd_mychip_create(struct snd_card *card,
struct pci_dev *pci,
struct mychip **rchip);
static int snd_mychip_free(struct mychip *chip);
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id);
static int __devinit snd_mychip_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id);
static void snd_mychip_remove(struct pci_dev *pci);
static int snd_mychip_dev_free(struct snd_device *device);
static int reserve_mem_regions(struct mychip *chip);
static void clear_mem_regions(struct mychip *chip);
static void memdump(struct mychip *chip);
/* ------------ PCM functions ------------- */
/* ---- constructor ---- */
static int __devinit snd_pcm_constructor(struct mychip *chip);
/* ---- destructor ---- */
static void snd_pcm_destructor(struct snd_pcm *pcm);
/* ---- file operations fcns ---- */
static int snd_pcm_playback_open(struct snd_pcm_substream *substream);
static int snd_pcm_playback_close(struct snd_pcm_substream *substream);
static int snd_pcm_capture_open(struct snd_pcm_substream *substream);
static int snd_pcm_capture_close(struct snd_pcm_substream *substream);
/*snd_pcm_lib_ioctl();*/
static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params);
static int snd_pcm_hw_free(struct snd_pcm_substream *substream);
static int snd_pcm_prepare(struct snd_pcm_substream *substream);
static int snd_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
static snd_pcm_uframes_t snd_pcm_pointer(struct snd_pcm_substream *substream);
/* ---------------------------------------- */
/**************************************************************************/
/************************* IMPLEMENTATION *******************************/
/*prototyped*/
static int snd_mychip_free(struct mychip *chip)
{
/* disable hardware here if any */
//.... /* (not implemented in this document) */
/* release the irq */
if (chip->irq >= 0)
free_irq(chip->irq, chip);
/* release the I/O ports & memory */
/*pci_release_regions(chip->pci);*/
clear_mem_regions(chip);
/* disable the PCI entry */
pci_disable_device(chip->pci);
/* release the data */
kfree(chip);
return 0;
}
/*prototyped*/
static int snd_mychip_dev_free(struct snd_device *device)
{
return snd_mychip_free(device->device_data);
}
/*prototyped*/
static void snd_mychip_remove(struct pci_dev *pci)
{
/*Clear the card data and PCI data*/
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
}
/* constructor -- see "Constructor" sub-section *//*prototyped*/
static int __devinit snd_mychip_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
struct mychip *chip;
int err;
printk(KERN_ERR "Probing ...\n");
/* (1) Check and increment the device index */
if (dev >= SNDRV_CARDS)
return -ENODEV;
if (!enable[dev]) {
dev++;
return -ENOENT;
}
/* (2) Create a card instance */
err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
if (err < 0)
return err;
/* (3) Create a main component */
/* chip-specific constructor: allocate PCI resources */
err = snd_mychip_create(card, pci, &chip);
if (err < 0) {
snd_card_free(card);
return err;
}
/* (4) Set driver ID and name strings */
strcpy(card->driver, "My Chip");
strcpy(card->shortname, "My Own Chip 123");
sprintf(card->longname, "%s at 0x%lx irq %i",
card->shortname, chip->port, chip->irq);
/* (5) Create other components PCM, mixers, MIDI etc */
/* implemented later */
/* (6) Register card instance */
err = snd_card_register(card);
if (err < 0) {
snd_card_free(card);
return err;
}
/* (7) Set the PCI driver data */
pci_set_drvdata(pci, card);
dev++;
/*Call PCM constructor*/
err = snd_pcm_constructor(chip);
if(err < 0)
printk(KERN_ERR "Failed to execute PCM constructor!\n");
printk(KERN_ERR "Probing done!\n");
return 0;
}
/*prototyped*/
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
{
struct mychip *chip = dev_id;
struct timeval timeval;
unsigned int status = 0;
static int executed = 0;
do_gettimeofday(&timeval);
if(executed < 10)
{
/*get the global status register*/
status = ioread32((void*)chip->memregs[IOREG_0].mem_mapped_addr + GLOBAL_STATUS_REGISTER_OFFSET);
status = ioread32((void*)chip->memregs[IOREG_1].mem_mapped_addr + GLOBAL_STATUS_REGISTER_OFFSET);
printk(KERN_ERR "\n---------- ISR -----------\n");
executed ++;
}
return IRQ_HANDLED;
}
/* chip-specific constructor *//*prototyped*/
static int __devinit snd_mychip_create(struct snd_card *card,
struct pci_dev *pci,
struct mychip **rchip)
{
struct mychip *chip;
int err;
static struct snd_device_ops ops = {
.dev_free = snd_mychip_dev_free,
};
printk(KERN_ERR "Enabling PCI device ...");
*rchip = NULL;
/* initialize the PCI entry */
err = pci_enable_device(pci);
if (err < 0)
return err;
/* check PCI availability (28bit DMA) */
if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
printk(KERN_ERR "error to set 28bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
}
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
/* initialize the stuff */
chip->card = card;
chip->pci = pci;
chip->irq = -1;
err = reserve_mem_regions(chip);
if (err < 0) {
kfree(chip);
pci_disable_device(pci);
return err;
}
/* (1) PCI resource allocation */
if (request_irq(pci->irq, snd_mychip_interrupt,
IRQF_SHARED, "My Chip", chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
printk(KERN_ERR "Gain access to PCI IRQ line ... line %d\n", pci->irq);
printk(KERN_ERR "Gain access to PCI IO ports ... ports 0x%x\n", (unsigned int)chip->port);
/* (2) initialization of the chip hardware */
/* (not implemented in this document) */
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
snd_mychip_free(chip);
return err;
}
snd_card_set_dev(card, &pci->dev);
*rchip = chip;
return 0;
}
static void memdump(struct mychip *chip)
{
int i;
for(i=0; i<BARS; i++)
{
printk(KERN_ERR "\n-----------------------------------\n");
printk(KERN_ERR "chip->memregs[i].bar = %d\n", chip->memregs[i].bar);
printk(KERN_ERR "chip->memregs[i].start_addr = 0x%x\n", chip->memregs[i].start_addr);
printk(KERN_ERR "chip->memregs[i].end_addr = 0x%x\n", chip->memregs[i].end_addr);
printk(KERN_ERR "chip->memregs[i].mem_len = %d\n", chip->memregs[i].mem_len);
printk(KERN_ERR "chip->memregs[i].flag = 0x%x\n", chip->memregs[i].flag);
printk(KERN_ERR "chip->memregs[i].mem_mapped_addr = 0x%p\n", chip->memregs[i].mem_mapped_addr);
}
}
static int reserve_mem_regions(struct mychip *chip)
{
int res = 0;
int i=0;
res = pci_request_regions(chip->pci, "My Chip");
if (res < 0) {
return res;
}
for(i=0; i<BARS; i++)
{
chip->memregs[i].bar = i;
chip->memregs[i].start_addr = pci_resource_start( chip->pci, i );
chip->memregs[i].end_addr = pci_resource_end( chip->pci, i );
chip->memregs[i].mem_len = pci_resource_len( chip->pci, i );
chip->memregs[i].flag = pci_resource_flags( chip->pci, i );
chip->memregs[i].mem_mapped_addr = pci_iomap(chip->pci, i, 0);
}
memdump(chip);
return res;
}
static void clear_mem_regions(struct mychip *chip)
{
int i = 0;
for(i=0; i<BARS; i++)
{
chip->memregs[i].bar = 0xFFFF;
chip->memregs[i].start_addr = 0;
chip->memregs[i].end_addr = 0;
chip->memregs[i].mem_len = 0;
chip->memregs[i].flag = 0xFFFF;
pci_iounmap(chip->pci, chip->memregs[i].mem_mapped_addr);
chip->memregs[i].mem_mapped_addr = NULL;
}
pci_release_regions(chip->pci);
}
/* ------------ PCM functions ------------- */
static struct snd_pcm_hardware snd_hardware_setup =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_8000_48000,
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = 128 * 1024,
.period_bytes_min = 32,
.period_bytes_max = 128 * 1024,
.periods_min = 1,
.periods_max = 1024,
.fifo_size = 0,
};
/* ---- operator structs ---- */
static struct snd_pcm_ops snd_pcm_playback_ops = {
.open = snd_pcm_playback_open,
.close = snd_pcm_playback_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_pcm_hw_params,
.hw_free = snd_pcm_hw_free,
.prepare = snd_pcm_prepare,
.trigger = snd_pcm_trigger,
.pointer = snd_pcm_pointer,
};
static struct snd_pcm_ops snd_pcm_capture_ops = {
.open = snd_pcm_capture_open,
.close = snd_pcm_capture_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_pcm_hw_params,
.hw_free = snd_pcm_hw_free,
.prepare = snd_pcm_prepare,
.trigger = snd_pcm_trigger,
.pointer = snd_pcm_pointer,
};
/* ---- file operations fcns ---- */
static int snd_pcm_capture_open(struct snd_pcm_substream *substream)
{
struct mychip *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int err = -10;
printk(KERN_ERR ">>> snd_pcm_capture_open()\n");
runtime->hw = snd_hardware_setup;
chip->substream = substream;
return err;
};
static int snd_pcm_capture_close(struct snd_pcm_substream *substream)
{
int err = -10;
printk(KERN_ERR ">>> snd_pcm_capture_close()\n");
return err;
};
static int snd_pcm_playback_open(struct snd_pcm_substream *substream)
{
struct mychip *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int err = -10;
printk(KERN_ERR ">>> snd_pcm_playback_open()\n");
runtime->hw = snd_hardware_setup;
chip->substream = substream;
return err;
};
static int snd_pcm_playback_close(struct snd_pcm_substream *substream)
{
int err = -10;
printk(KERN_ERR ">>> snd_pcm_playback_close()\n");
return err;
};
/*snd_pcm_lib_ioctl();*/
static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
int err = 0;
return err;
};
static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
{
int err = 0;
return err;
};
static int snd_pcm_prepare(struct snd_pcm_substream *substream)
{
int err = 0;
return err;
};
static int snd_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
int err = 0;
return err;
};
static snd_pcm_uframes_t snd_pcm_pointer(struct snd_pcm_substream *substream)
{
int err = 0;
return err;
};
/* ---- constructor ---- */
static int __devinit snd_pcm_constructor(struct mychip *chip)
{
struct snd_pcm *pcm = NULL;
int err = 0;
printk(KERN_ERR ">>> PCM CONSTRUCTOR: running...\n");
err = snd_pcm_new(chip->card, "My Own Chip", 0, 1, 1, &pcm);
if(err < 0)
{
printk(KERN_ERR ">>> PCM CONSTRUCTOR: Failed to execute snd_pcm_new()!\n");
return err;
}
pcm->private_data = chip;
pcm->private_free = snd_pcm_destructor;
strcpy(pcm->name, "My Own Chip");
chip->pcm = pcm;
/*set operators*/
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_pcm_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_pcm_capture_ops);
/*stream preallocation of buffers*/
err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 64*1024, 64*1024);
if(err < 0)
{
printk(KERN_ERR ">>> PCM CONSTRUCTOR: Failed to execute snd_pcm_lib_preallocate_pages_for_all()!\n");
return err;
}
printk(KERN_ERR ">>> PCM CONSTRUCTOR: ... exiting.\n");
return 0;
}
/* ---- destructor ---- */
static void snd_pcm_destructor(struct snd_pcm *pcm)
{
/*
struct mychip *chip = snd_pcm_chip(pcm);
*/
}
/* ---------------------------------------- */
/* PCI IDs */
static struct pci_device_id snd_mychip_ids[] = {
{ VENDOR_ID, DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
/* pci_driver definition */
static struct pci_driver driver = {
.name = "My Own Chip",
.id_table = snd_mychip_ids,
.probe = snd_mychip_probe,
.remove = __devexit_p(snd_mychip_remove),
};
/**************** MODULE EXCUTED FUNCTIONS ****************************/
/* module initialization */
static int __init alsa_card_mychip_init(void)
{
printk(KERN_ERR "\n\n\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
printk(KERN_ERR "-->>> Module init: !!!");
return pci_register_driver(&driver);
}
/* module clean up */
static void __exit alsa_card_mychip_exit(void)
{
pci_unregister_driver(&driver);
printk(KERN_ERR "-->>> Module exit: ");
}
module_init(alsa_card_mychip_init)
module_exit(alsa_card_mychip_exit)
我从 dmesg 得到的输出:
[ 227.202006] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
[ 227.202430] -->>> Module init: !!!
[ 227.202507] Probing ...
[ 227.203959] Enabling PCI device ...
[ 227.207882]
[ 227.207882] -----------------------------------
[ 227.208097] chip->memregs[i].bar = 0
[ 227.208124] chip->memregs[i].start_addr = 0xd100
[ 227.208148] chip->memregs[i].end_addr = 0xd1ff
[ 227.208174] chip->memregs[i].mem_len = 256
[ 227.208198] chip->memregs[i].flag = 0x40101
[ 227.208223] chip->memregs[i].mem_mapped_addr = 0x0001d100
[ 227.208246]
[ 227.208246] -----------------------------------
[ 227.208271] chip->memregs[i].bar = 1
[ 227.208294] chip->memregs[i].start_addr = 0xd200
[ 227.208318] chip->memregs[i].end_addr = 0xd23f
[ 227.208341] chip->memregs[i].mem_len = 64
[ 227.208364] chip->memregs[i].flag = 0x40101
[ 227.208388] chip->memregs[i].mem_mapped_addr = 0x0001d200
[ 227.208410]
[ 227.208410] -----------------------------------
[ 227.208435] chip->memregs[i].bar = 2
.....
[ 227.209080] Gain access to PCI IRQ line ... line 5
[ 227.209104] Gain access to PCI IO ports ... ports 0x0
[ 227.224202] >>> PCM CONSTRUCTOR: running...
[ 227.225378] >>> PCM CONSTRUCTOR: ... exiting.
[ 227.225403] Probing done!
[ 227.295404]
[ 227.295404] ---------- ISR -----------
[ 227.313297]
[ 227.313297] ---------- ISR -----------
[ 227.327248]
[ 227.327248] ---------- ISR -----------
[ 227.344968]
[ 227.344968] ---------- ISR -----------
[ 227.351703]
[ 227.351703] ---------- ISR -----------
[ 227.360189]
[ 227.360189] ---------- ISR -----------
[ 227.371751]
[ 227.371751] ---------- ISR -----------
[ 227.387809]
[ 227.387809] ---------- ISR -----------
[ 227.396767]
[ 227.396767] ---------- ISR -----------
[ 227.413297]
[ 227.413297] ---------- ISR -----------
你看到这里
还有我申请中的一些行:
/* Open PCM device for playback. */
rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (rc < 0) {
printf(
"unable to open pcm device: %s\n",
snd_strerror(rc));
exit(1);
}
printf("Device opened ... rc = %d \n", rc);
在这里,我尝试打开我的设备。如果你注意 playback_open() 函数上面的驱动程序代码,应该会 printk() 一些消息并且应该返回 -10。我是故意这样做的。但是我的应用程序显示 snd_pcm_open() 的结果是可以的(我的意思是零)。所以看起来我的应用程序没有看到我的驱动程序,而是尝试使用其他东西。
我还将放置当前正在加载的模块的所有声音:
Module Size Used by
...
alsa 13273 0 //this is my driver
snd_ac97_codec 105592 0
snd_pcm 80357 2 alsa,snd_ac97_codec
snd_page_alloc 14036 1 snd_pcm
ac97_bus 12670 1 snd_ac97_codec
snd_seq_midi 13132 0
snd_rawmidi 25382 1 snd_seq_midi
snd_seq_midi_event 14475 1 snd_seq_midi
snd_seq 51256 2 snd_seq_midi,snd_seq_midi_event
snd_timer 24503 2 snd_pcm,snd_seq
snd_seq_device 14137 3 snd_seq_midi,snd_rawmidi,snd_seq
snd 62027 7 alsa,snd_ac97_codec,snd_pcm,snd_rawmidi,
snd_seq,snd_timer,snd_seq_device
soundcore 14599 1 snd
这是 lspci -v 的输出,它将显示音频设备的信息:
00:05.0 Multimedia audio controller: Intel Corporation 82801AA AC'97 Audio Controller (rev 01)
Subsystem: Intel Corporation Device 0000
Flags: bus master, medium devsel, latency 0, IRQ 5
I/O ports at d100 [size=256]
I/O ports at d200 [size=64]
Kernel driver in use: My Own Chip
Kernel modules: snd-nedelinxalsaxpci, snd-intel8x0
我用我的驱动程序构建我的内核,因为我认为这可能有帮助,但它没有(snd-nedelinxalsaxpci 是我的驱动程序,而 snd-intel8x0 是原始模块)。 “我自己的芯片”来 self 的司机。
我不知道我还能给你什么其他信息。非常感谢您的支持。
最佳答案
您的问题是您在调用 snd_card_register
之后 调用 PCM 构造函数。声卡设备只有在创建后注册后才能被用户空间访问。
您的代码中甚至有一条注释告诉您执行此操作的正确位置:
/* (5) Create other components PCM, mixers, MIDI etc */
关于linux - 自定义 ALSA 驱动程序不执行 struct snd_pcm_ops 中的开放函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14159161/
我正在尝试使用 ALSA 创建我自己的自定义声音驱动程序。到目前为止,我已经成功加载了模块,我的意思是: 我的探测函数已执行 执行构造函数 我看到正在执行中断 我通过放置在这些函数中的转储发现了这一点
我是一名优秀的程序员,十分优秀!