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

📄 audio.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
                oprintk((" started as (0x%x)\n", BAL_TO_OSS(l,m)));                i = OSS_TO_GAIN(k);                j = OSS_TO_BAL(k);                oprintk((" for stereo to %d (bal %d)\n", i, j));                if (drv->ops->set_output_volume)                        drv->ops->set_output_volume(drv, i);                if (drv->ops->set_output_balance)                        drv->ops->set_output_balance(drv, j);        case SOUND_MIXER_READ_PCM:                if (drv->ops->get_output_volume)                        i = drv->ops->get_output_volume(drv);                if (drv->ops->get_output_balance)                        j = drv->ops->get_output_balance(drv);                oprintk((" got 0x%x\n", BAL_TO_OSS(i,j)));                i = BAL_TO_OSS(i,j);                /* Try to be reasonable about volume changes */                if ((cmd == SOUND_MIXER_WRITE_PCM) && (i != k) &&                     (i == BAL_TO_OSS(l,m))) {                        k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256;                        k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1;                        oprintk((" try 0x%x\n", k));                        goto oretry;                }                return COPY_OUT(arg, i);        case SOUND_MIXER_READ_SPEAKER:                k = OSS_PORT_AUDIO(drv, AUDIO_SPEAKER);                return COPY_OUT(arg, k);        case SOUND_MIXER_READ_MIC:                k = OSS_IPORT_AUDIO(drv, AUDIO_MICROPHONE);                return COPY_OUT(arg, k);        case SOUND_MIXER_READ_CD:                k = OSS_IPORT_AUDIO(drv, AUDIO_CD);                return COPY_OUT(arg, k);        case SOUND_MIXER_READ_LINE:                k = OSS_IPORT_AUDIO(drv, AUDIO_LINE_IN);                return COPY_OUT(arg, k);        case SOUND_MIXER_READ_LINE1:                k = OSS_PORT_AUDIO(drv, AUDIO_HEADPHONE);                return COPY_OUT(arg, k);        case SOUND_MIXER_READ_LINE2:                k = OSS_PORT_AUDIO(drv, AUDIO_LINE_OUT);                return COPY_OUT(arg, k);        case SOUND_MIXER_WRITE_MIC:        case SOUND_MIXER_WRITE_CD:        case SOUND_MIXER_WRITE_LINE:        case SOUND_MIXER_WRITE_LINE1:        case SOUND_MIXER_WRITE_LINE2:        case SOUND_MIXER_WRITE_SPEAKER:                if(COPY_IN(arg, k))                        return -EFAULT;                OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_LINE, AUDIO_LINE_IN, k);                OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_MIC, AUDIO_MICROPHONE, k);                OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_CD, AUDIO_CD, k);                OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_SPEAKER, AUDIO_SPEAKER, k);                OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE1, AUDIO_HEADPHONE, k);                OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE2, AUDIO_LINE_OUT, k);                return COPY_OUT(arg, k);        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 COPY_OUT(arg, j);  case SOUND_MIXER_WRITE_RECSRC:           if (!drv->ops->set_input_port)                  return -EINVAL;          if(COPY_IN(arg, k))                  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 COPY_OUT(arg, i);        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 COPY_OUT(arg, j);        case SOUND_MIXER_READ_CAPS: /* mixer capabilities */                i = SOUND_CAP_EXCL_INPUT;                return COPY_OUT(arg, i);        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 COPY_OUT(arg, j);        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);                        COPY_OUT(arg, j);                        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;                        COPY_OUT(arg, j);                        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))

⌨️ 快捷键说明

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