免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4046 | 回复: 3
打印 上一主题 下一主题

Linux下音频驱动!! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-04 19:15 |只看该作者 |倒序浏览
这程序可谓是初学者(驱动开发),要学的最为经典的程序之篇!
一大段代码看下来,了解过程!的确要一点时间功夫!!
现在一点就是对,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;
}

论坛徽章:
0
2 [报告]
发表于 2009-03-04 19:41 |只看该作者
有什么意思么?你提的那几个问题肯定跟硬件的要求有关,没啥研究价值啊~

论坛徽章:
0
3 [报告]
发表于 2009-03-04 23:20 |只看该作者
这些宏都是从硬件手册上得来的

论坛徽章:
0
4 [报告]
发表于 2009-03-05 13:34 |只看该作者
看看datasheet就明白了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP