📄 audio.c
字号:
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 + -