⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.c

📁 自己根据lkd和情境分析
💻 C
📖 第 1 页 / 共 5 页
字号:
                return put_user(k, (int *)arg);        case SOUND_MIXER_READ_RECSRC:                 if (drv->ops->get_input_port)                        i = drv->ops->get_input_port(drv);                /* only one should ever be selected */                if (i & AUDIO_CD) j = SOUND_MASK_CD;                if (i & AUDIO_LINE_IN) j = SOUND_MASK_LINE;                if (i & AUDIO_MICROPHONE) j = SOUND_MASK_MIC;                    return put_user(j, (int *)arg);  case SOUND_MIXER_WRITE_RECSRC:           if (!drv->ops->set_input_port)                  return -EINVAL;          if (get_user(k, (int *)arg))                  return -EFAULT;          /* only one should ever be selected */          if (k & SOUND_MASK_CD) j = AUDIO_CD;          if (k & SOUND_MASK_LINE) j = AUDIO_LINE_IN;          if (k & SOUND_MASK_MIC) j = AUDIO_MICROPHONE;          oprintk(("setting inport to %d\n", j));          i = drv->ops->set_input_port(drv, j);              return put_user(i, (int *)arg);        case SOUND_MIXER_READ_RECMASK:                 if (drv->ops->get_input_ports)                        i = drv->ops->get_input_ports(drv);                /* what do we support? */                if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC;                if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE;                if (i & AUDIO_CD) j |= SOUND_MASK_CD;                    return put_user(j, (int *)arg);        case SOUND_MIXER_READ_CAPS: /* mixer capabilities */                i = SOUND_CAP_EXCL_INPUT;                return put_user(i, (int *)arg);        case SOUND_MIXER_READ_DEVMASK: /* all supported devices */                if (drv->ops->get_input_ports)                        i = drv->ops->get_input_ports(drv);                /* what do we support? */                if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC;                if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE;                if (i & AUDIO_CD) j |= SOUND_MASK_CD;                    if (drv->ops->get_output_ports)                        i = drv->ops->get_output_ports(drv);                if (i & AUDIO_SPEAKER) j |= SOUND_MASK_SPEAKER;                if (i & AUDIO_HEADPHONE) j |= SOUND_MASK_LINE1;                if (i & AUDIO_LINE_OUT) j |= SOUND_MASK_LINE2;                j |= SOUND_MASK_VOLUME;        case SOUND_MIXER_READ_STEREODEVS: /* what supports stereo */                j |= SOUND_MASK_PCM|SOUND_MASK_RECLEV;                if (cmd == SOUND_MIXER_READ_STEREODEVS)                        j &= ~(MONO_DEVICES);                return put_user(j, (int *)arg);        default:                return -EINVAL;        };}/* AUDIO_SETINFO uses these to set values if possible. */static __inline__ int __sparcaudio_if_set_do(struct sparcaudio_driver *drv, 		       int (*set_function)(struct sparcaudio_driver *, int), 		       int (*get_function)(struct sparcaudio_driver *), 		       unsigned int value){        if (set_function && Modify(value))                return (int) set_function(drv, value);        else if (get_function)                return (int) get_function(drv);        else                 return 0;}static __inline__ int __sparcaudio_if_setc_do(struct sparcaudio_driver *drv, 			int (*set_function)(struct sparcaudio_driver *, int), 			int (*get_function)(struct sparcaudio_driver *), 			unsigned char value){        if (set_function && Modifyc(value))                return (char) set_function(drv, (int)value);        else if (get_function)                return (char) get_function(drv);        else                 return 0;}/* I_FLUSH, I_{G,S}ETSIG, I_NREAD provided for SunOS compatibility * * I must admit I'm quite ashamed of the state of the ioctl handling, * but I do have several optimizations which I'm planning. -- DJB */static int sparcaudio_ioctl(struct inode * inode, struct file * file,			    unsigned int cmd, unsigned long arg){	int retval = 0, i, j, k;	int minor = MINOR(inode->i_rdev);	struct audio_info ainfo;	audio_buf_info binfo;	count_info cinfo;	struct sparcaudio_driver *drv =                 drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)];	switch (minor & 0xf) {	case SPARCAUDIO_MIXER_MINOR:                return sparcaudio_mixer_ioctl(inode, file, cmd, (unsigned int *)arg);	case SPARCAUDIO_DSP16_MINOR:        case SPARCAUDIO_DSP_MINOR:	case SPARCAUDIO_AUDIO_MINOR:	case SPARCAUDIO_AUDIOCTL_MINOR:                /* According to the OSS prog int, you can mixer ioctl /dev/dsp */                if (_IOC_TYPE(cmd) == 'M')                        return sparcaudio_mixer_ioctl(inode,                                                       file, cmd, (unsigned int *)arg);                switch (cmd) {                case I_GETSIG:                case I_GETSIG_SOLARIS:                        j = (int) lis_get_elist_ent(drv->sd_siglist,current->pid);                        put_user(j, (int *)arg);                        retval = drv->input_count;                        break;                case I_SETSIG:                case I_SETSIG_SOLARIS:                        if ((minor & 0xf) == SPARCAUDIO_AUDIOCTL_MINOR) {                                if (!arg) {                                        if (lis_del_from_elist(&(drv->sd_siglist),                                                               current->pid,S_ALL)) {                                                retval = -EINVAL;                                        } else if (!drv->sd_siglist) {                                                drv->sd_sigflags=0;                                        }                                } else if (lis_add_to_elist(&(drv->sd_siglist),                                                            current->pid,                                                            (short)arg)) {                                        retval = -EAGAIN;                                } else {                                        ((drv->sd_sigflags) |= (arg));                                }                        }                        break;                case I_NREAD:                case I_NREAD_SOLARIS:                        /* According to the Solaris man page, this copies out                         * the size of the first streams buffer and returns                          * the number of streams messages on the read queue as                         * as its retval. (streamio(7I)) This should work.                         */                        j = (drv->input_count > 0) ? drv->input_buffer_size : 0;                        put_user(j, (int *)arg);                        retval = drv->input_count;                        break;                        /* A poor substitute until we do true resizable buffers. */                case SNDCTL_DSP_GETISPACE:                        binfo.fragstotal = drv->num_input_buffers;                        binfo.fragments = drv->num_input_buffers -                                 (drv->input_count + drv->recording_count);                        binfo.fragsize = drv->input_buffer_size;                        binfo.bytes = binfo.fragments*binfo.fragsize;	                            retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo));                        if (retval)                                break;                        copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo));                        break;                case SNDCTL_DSP_GETOSPACE:                        binfo.fragstotal = drv->num_output_buffers;                        binfo.fragments = drv->num_output_buffers -                                 (drv->output_count + drv->playing_count +                                  (drv->output_offset ? 1 : 0));                        binfo.fragsize = drv->output_buffer_size;                        binfo.bytes = binfo.fragments*binfo.fragsize +                                 (drv->output_buffer_size - drv->output_offset);	                            retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo));                        if (retval)                                break;                        copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo));                        break;                case SNDCTL_DSP_GETIPTR:                case SNDCTL_DSP_GETOPTR:                        /* int bytes (number of bytes read/written since last)                         * int blocks (number of frags read/wrote since last call)                         * int ptr (current position of dma in buffer)                         */                        retval = 0;                        cinfo.bytes = 0;                        cinfo.ptr = 0;                        cinfo.blocks = 0;                        cinfo.bytes += cinfo.ptr;	                            retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(cinfo));                        if (retval)                                break;                        copy_to_user(&((char *)arg)[0], (char *)&cinfo, sizeof(cinfo));                        break;                case SNDCTL_DSP_SETFRAGMENT:                        /* XXX Small hack to get ESD/Enlightenment to work.  --DaveM */                        retval = 0;                        break;                case SNDCTL_DSP_SUBDIVIDE:                        /* I don't understand what I need to do yet. */                        retval = -EINVAL;                        break;                case SNDCTL_DSP_SETTRIGGER:                        /* This may not be 100% correct */                        if ((arg & PCM_ENABLE_INPUT) && drv->ops->get_input_pause &&                            drv->ops->set_input_pause) {                                if (drv->ops->get_input_pause(drv))                                        drv->ops->set_input_pause(drv, 0);                        } else {                                if (!drv->ops->get_input_pause(drv))                                        drv->ops->set_input_pause(drv, 1);                        }                        if ((arg & PCM_ENABLE_OUTPUT) && drv->ops->get_output_pause &&                            drv->ops->set_output_pause) {                                if (drv->ops->get_output_pause(drv))                                        drv->ops->set_output_pause(drv, 0);                        } else {                                if (!drv->ops->get_output_pause(drv))                                        drv->ops->set_output_pause(drv, 1);                        }                        break;                case SNDCTL_DSP_GETTRIGGER:                        j = 0;                        if (drv->ops->get_input_pause) {                                if (drv->ops->get_input_pause(drv))                                        j = PCM_ENABLE_INPUT;                        }                        if (drv->ops->get_output_pause) {                                if (drv->ops->get_output_pause(drv))                                        j |= PCM_ENABLE_OUTPUT;                        }                        put_user(j, (int *)arg);                        break;                case SNDCTL_DSP_GETBLKSIZE:                        j = drv->input_buffer_size;                        put_user(j, (int *)arg);                        break;                case SNDCTL_DSP_SPEED:                        if ((!drv->ops->set_output_rate) &&                             (!drv->ops->set_input_rate)) {                                retval = -EINVAL;                                break;                        }                        get_user(i, (int *)arg)                        tprintk(("setting speed to %d\n", i));                        drv->ops->set_input_rate(drv, i);                        drv->ops->set_output_rate(drv, i);                        j = drv->ops->get_output_rate(drv);                        put_user(j, (int *)arg);                        break;                case SNDCTL_DSP_GETCAPS:                        /* All Sparc audio hardware is full duplex.                         * 4231 supports DMA pointer reading, 7930 is byte at a time.                         * Pause functionality emulates trigger                         */                        j = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER | DSP_CAP_REALTIME;                        put_user(j, (int *)arg);                        break;                case SNDCTL_DSP_GETFMTS:                        if (drv->ops->get_formats) {                                j = drv->ops->get_formats(drv);                                put_user(j, (int *)arg);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -