Linux下音频驱动!!

发布于 2022-09-18 19:15:13 字数 22541 浏览 11 评论 0

这程序可谓是初学者(驱动开发),要学的最为经典的程序之篇!
一大段代码看下来,了解过程!的确要一点时间功夫!!
现在一点就是对,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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

宫墨修音 2022-09-25 19:15:13

有什么意思么?你提的那几个问题肯定跟硬件的要求有关,没啥研究价值啊~

ㄖ落Θ余辉 2022-09-25 19:15:13

这些宏都是从硬件手册上得来的

美胚控场 2022-09-25 19:15:13

看看datasheet就明白了

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文