Linux下音频驱动!!
这程序可谓是初学者(驱动开发),要学的最为经典的程序之篇!
一大段代码看下来,了解过程!的确要一点时间功夫!!
现在一点就是对,DSP控制那一块有一点迷惑!不知道那些宏是怎么得到来的!
比如:SNDCTL_DSP_SETFMT这个定义是怎么得来的!
在内核里面对此是这样链接的
#define SIOCPARM_MASK 0x1fff /* parameters must be < 8192 bytes */
#define SIOC_OUT 0x20000000 /* copy out parameters */
#define SIOC_IN 0x40000000 /* copy in parameters */
#define SIOC_INOUT (SIOC_IN|SIOC_OUT)
#define SNDCTL_DSP_SETFMT _SIOWR('P',5, int) /* Selects ONE fmt*/
#define _SIOWR(x,y,t) ((int)(SIOC_INOUT|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<|y))
就是对以下这三个定义不知道是怎么回事!!
#define SIOCPARM_MASK 0x1fff /* parameters must be < 8192 bytes */
#define SIOC_OUT 0x20000000 /* copy out parameters */
#define SIOC_IN 0x40000000 /* copy in parameters */
那位前辈百忙这中,指点一下!谢谢!!!
发下为驱动控制DSP源码!!
-------------------------------------------------------------------------------------------
static int smdk2410_audio_ioctl(struct inode *inode, struct file *file,
uint cmd, ulong arg)
{
long val;
//printk(KERN_ERR "line %d passed!\n",__LINE__);
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, (int *)arg);
case SNDCTL_DSP_SETFMT:
get_user(val, (long *) arg);
if (val & AUDIO_FMT_MASK) {
audio_fmt = val;
break;
} else
return -EINVAL;
case SNDCTL_DSP_CHANNELS:
case SNDCTL_DSP_STEREO:
get_user(val, (long *) arg);
if (cmd == SNDCTL_DSP_STEREO)
val = val ? 2 : 1;
if (val != 1 && val != 2)
return -EINVAL;
audio_channels = val;
break;
case SOUND_PCM_READ_CHANNELS:
put_user(audio_channels, (long *) arg);
break;
case SNDCTL_DSP_SPEED:
get_user(val, (long *) arg);
val = audio_set_dsp_speed(val);
if (val < 0)
return -EINVAL;
put_user(val, (long *) arg);
break;
case SOUND_PCM_READ_RATE:
put_user(audio_rate, (long *) arg);
break;
case SNDCTL_DSP_GETFMTS:
put_user(AUDIO_FMT_MASK, (long *) arg);
break;
case SNDCTL_DSP_GETBLKSIZE:
if(file->f_mode & FMODE_WRITE)
return put_user(audio_fragsize, (long *) arg);
else
return put_user(audio_fragsize, (int *) arg);
case SNDCTL_DSP_SETFRAGMENT:
if (file->f_mode & FMODE_WRITE) {
if (output_stream.buffers)
return -EBUSY;
get_user(val, (long *) arg);
audio_fragsize = 1 << (val & 0xFFFF);
if (audio_fragsize < 16)
audio_fragsize = 16;
if (audio_fragsize > 16384)
audio_fragsize = 16384;
audio_nbfrags = (val >> 16) & 0x7FFF;
if (audio_nbfrags < 2)
audio_nbfrags = 2;
if (audio_nbfrags * audio_fragsize > 128 * 1024)
audio_nbfrags = 128 * 1024 / audio_fragsize;
if (audio_setup_buf(&output_stream))
return -ENOMEM;
}
if (file->f_mode & FMODE_READ) {
if (input_stream.buffers)
return -EBUSY;
get_user(val, (int *) arg);
audio_fragsize = 1 << (val & 0xFFFF);
if (audio_fragsize < 16)
audio_fragsize = 16;
if (audio_fragsize > 16384)
audio_fragsize = 16384;
audio_nbfrags = (val >> 16) & 0x7FFF;
if (audio_nbfrags < 2)
audio_nbfrags = 2;
if (audio_nbfrags * audio_fragsize > 128 * 1024)
audio_nbfrags = 128 * 1024 / audio_fragsize;
if (audio_setup_buf(&input_stream))
return -ENOMEM;
}
break;
case SNDCTL_DSP_SYNC:
return audio_sync(file);
case SNDCTL_DSP_GETOSPACE:
{
audio_stream_t *s = &output_stream;
audio_buf_info *inf = (audio_buf_info *) arg;
int err = verify_area(VERIFY_WRITE, inf, sizeof(*inf));
int i;
int frags = 0, bytes = 0;
if (err)
return err;
for (i = 0; i < s->nbfrags; i++) {
if (atomic_read(&s->buffers.sem.count) > 0) {
if (s->buffers.size == 0) frags++;
bytes += s->fragsize - s->buffers.size;
}
}
put_user(frags, &inf->fragments);
put_user(s->nbfrags, &inf->fragstotal);
put_user(s->fragsize, &inf->fragsize);
put_user(bytes, &inf->bytes);
break;
}
case SNDCTL_DSP_GETISPACE:
{
audio_stream_t *s = &input_stream;
audio_buf_info *inf = (audio_buf_info *) arg;
int err = verify_area(VERIFY_WRITE, inf, sizeof(*inf));
int i;
int frags = 0, bytes = 0;
if (!(file->f_mode & FMODE_READ))
return -EINVAL;
if (err)
return err;
for(i = 0; i < s->nbfrags; i++){
if (atomic_read(&s->buffers.sem.count) > 0)
{
if (s->buffers.size == s->fragsize)
frags++;
bytes += s->buffers.size;
}
}
put_user(frags, &inf->fragments);
put_user(s->nbfrags, &inf->fragstotal);
put_user(s->fragsize, &inf->fragsize);
put_user(bytes, &inf->bytes);
break;
}
case SNDCTL_DSP_RESET:
if (file->f_mode & FMODE_READ) {
audio_clear_buf(&input_stream);
}
if (file->f_mode & FMODE_WRITE) {
audio_clear_buf(&output_stream);
}
return 0;
case SNDCTL_DSP_NONBLOCK:
file->f_flags |= O_NONBLOCK;
return 0;
case SNDCTL_DSP_POST:
case SNDCTL_DSP_SUBDIVIDE:
case SNDCTL_DSP_GETCAPS:
case SNDCTL_DSP_GETTRIGGER:
case SNDCTL_DSP_SETTRIGGER:
case SNDCTL_DSP_GETIPTR:
case SNDCTL_DSP_GETOPTR:
case SNDCTL_DSP_MAPINBUF:
case SNDCTL_DSP_MAPOUTBUF:
case SNDCTL_DSP_SETSYNCRO:
case SNDCTL_DSP_SETDUPLEX:
return -ENOSYS;
default:
return smdk2410_mixer_ioctl(inode, file, cmd, arg);
}
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
有什么意思么?你提的那几个问题肯定跟硬件的要求有关,没啥研究价值啊~
这些宏都是从硬件手册上得来的
看看datasheet就明白了