static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int len = 0, dtype; int dev = iminor(file->f_dentry->d_inode); long ret = -EINVAL; void __user *p = (void __user *)arg; if (_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0) { /* * Have to validate the address given by the process. */ len = _SIOC_SIZE(cmd); if (len < 1 || len > 65536 || !p) return -EFAULT; if (_SIOC_DIR(cmd) & _SIOC_WRITE) if (!access_ok(VERIFY_READ, p, len)) return -EFAULT; if (_SIOC_DIR(cmd) & _SIOC_READ) if (!access_ok(VERIFY_WRITE, p, len)) return -EFAULT; } DEB(printk("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg)); if (cmd == OSS_GETVERSION) return __put_user(SOUND_VERSION, (int __user *)p); lock_kernel(); if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 && /* Mixer ioctl */ (dev & 0x0f) != SND_DEV_CTL) { dtype = dev & 0x0f; switch (dtype) { case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: ret = sound_mixer_ioctl(audio_devs[dev >> 4]->mixer_dev, cmd, p); break; default: ret = sound_mixer_ioctl(dev >> 4, cmd, p); break; } unlock_kernel(); return ret; }
static int sound_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int err, len = 0, dtype; int dev = MINOR(inode->i_rdev); if (_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0) { /* * Have to validate the address given by the process. */ len = _SIOC_SIZE(cmd); if (len < 1 || len > 65536 || arg == 0) return -EFAULT; if (_SIOC_DIR(cmd) & _SIOC_WRITE) if ((err = verify_area(VERIFY_READ, (void *)arg, len)) < 0) return err; if (_SIOC_DIR(cmd) & _SIOC_READ) if ((err = verify_area(VERIFY_WRITE, (void *)arg, len)) < 0) return err; } DEB(printk("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg)); if (cmd == OSS_GETVERSION) return __put_user(SOUND_VERSION, (int *)arg); if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 && /* Mixer ioctl */ (dev & 0x0f) != SND_DEV_CTL) { dtype = dev & 0x0f; switch (dtype) { #ifdef CONFIG_AUDIO case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: return sound_mixer_ioctl(audio_devs[dev >> 4]->mixer_dev, cmd, (caddr_t)arg); #endif default: return sound_mixer_ioctl(dev >> 4, cmd, (caddr_t)arg); } }
static int sound_mixer_ioctl(int mixdev, unsigned int cmd, void __user *arg) { if (mixdev < 0 || mixdev >= MAX_MIXER_DEV) return -ENXIO; /* Try to load the mixer... */ if (mixer_devs[mixdev] == NULL) { request_module("mixer%d", mixdev); } if (mixdev >= num_mixers || !mixer_devs[mixdev]) return -ENXIO; if (cmd == SOUND_MIXER_INFO) return get_mixer_info(mixdev, arg); if (cmd == SOUND_OLD_MIXER_INFO) return get_old_mixer_info(mixdev, arg); if (_SIOC_DIR(cmd) & _SIOC_WRITE) mixer_devs[mixdev]->modify_counter++; if (!mixer_devs[mixdev]->ioctl) return -EINVAL; return mixer_devs[mixdev]->ioctl(mixdev, cmd, arg); }
static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct video_audio va; int left,right,ret,val = 0; struct TVMIXER *mix = file->private_data; struct i2c_client *client = mix->dev; if (NULL == client) return -ENODEV; if (cmd == SOUND_MIXER_INFO) { mixer_info info; strncpy(info.id, "tv card", sizeof(info.id)); strncpy(info.name, client->name, sizeof(info.name)); info.modify_counter = 42 /* FIXME */; if (copy_to_user((void *)arg, &info, sizeof(info))) return -EFAULT; return 0; } if (cmd == SOUND_OLD_MIXER_INFO) { _old_mixer_info info; strncpy(info.id, "tv card", sizeof(info.id)); strncpy(info.name, client->name, sizeof(info.name)); if (copy_to_user((void *)arg, &info, sizeof(info))) return -EFAULT; return 0; } if (cmd == OSS_GETVERSION) return put_user(SOUND_VERSION, (int *)arg); if (_SIOC_DIR(cmd) & _SIOC_WRITE) if (get_user(val, (int *)arg)) return -EFAULT; /* read state */ memset(&va,0,sizeof(va)); client->driver->command(client,VIDIOCGAUDIO,&va); switch (cmd) { case MIXER_READ(SOUND_MIXER_RECMASK): case MIXER_READ(SOUND_MIXER_CAPS): case MIXER_READ(SOUND_MIXER_RECSRC): case MIXER_WRITE(SOUND_MIXER_RECSRC): ret = 0; break; case MIXER_READ(SOUND_MIXER_STEREODEVS): ret = SOUND_MASK_VOLUME; break; case MIXER_READ(SOUND_MIXER_DEVMASK): ret = SOUND_MASK_VOLUME; if (va.flags & VIDEO_AUDIO_BASS) ret |= SOUND_MASK_BASS; if (va.flags & VIDEO_AUDIO_TREBLE) ret |= SOUND_MASK_TREBLE; break; case MIXER_WRITE(SOUND_MIXER_VOLUME): left = mix_to_v4l(val); right = mix_to_v4l(val >> 8); va.volume = MAX(left,right); va.balance = (32768*MIN(left,right)) / (va.volume ? va.volume : 1); va.balance = (left<right) ? (65535-va.balance) : va.balance; client->driver->command(client,VIDIOCSAUDIO,&va); client->driver->command(client,VIDIOCGAUDIO,&va); /* fall throuth */ case MIXER_READ(SOUND_MIXER_VOLUME): left = (MIN(65536 - va.balance,32768) * va.volume) / 32768; right = (MIN(va.balance,32768) * va.volume) / 32768; ret = v4l_to_mix2(left,right); break; case MIXER_WRITE(SOUND_MIXER_BASS): va.bass = mix_to_v4l(val); client->driver->command(client,VIDIOCSAUDIO,&va); client->driver->command(client,VIDIOCGAUDIO,&va); /* fall throuth */ case MIXER_READ(SOUND_MIXER_BASS): ret = v4l_to_mix(va.bass); break; case MIXER_WRITE(SOUND_MIXER_TREBLE): va.treble = mix_to_v4l(val); client->driver->command(client,VIDIOCSAUDIO,&va); client->driver->command(client,VIDIOCGAUDIO,&va); /* fall throuth */ case MIXER_READ(SOUND_MIXER_TREBLE): ret = v4l_to_mix(va.treble); break; default: return -EINVAL; } if (put_user(ret, (int *)arg)) return -EFAULT; return 0; }
static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) { int cmdf = cmd & 0xff; opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc; switch(cmdf) { case SOUND_MIXER_VOLUME: case SOUND_MIXER_MIC: case SOUND_MIXER_BASS: case SOUND_MIXER_TREBLE: case SOUND_MIXER_DEVMASK: case SOUND_MIXER_STEREODEVS: case SOUND_MIXER_RECMASK: case SOUND_MIXER_CAPS: case SOUND_MIXER_RECSRC: break; default: return call_ad_mixer(devc, cmd, arg); } if(((cmd >> 8) & 0xff) != 'M') return -EINVAL; if(_SIOC_DIR (cmd) & _SIOC_WRITE) { switch (cmdf) { case SOUND_MIXER_RECSRC: if(devc->ad_mixer_dev != -1) return call_ad_mixer(devc, cmd, arg); else { if(*(int*)arg != 0) return -EINVAL; return 0; } case SOUND_MIXER_VOLUME: arg_to_volume_stereo(*(unsigned int*)arg, &devc->volume_l, &devc->volume_r); opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r); *(int*)arg = ret_vol_stereo(devc->volume_l, devc->volume_r); return 0; case SOUND_MIXER_MIC: arg_to_volume_mono(*(unsigned int*)arg, &devc->mic); opl3sa2_set_mic(devc, devc->mic); *(int*)arg = ret_vol_mono(devc->mic); return 0; case SOUND_MIXER_BASS: if(chipset != CHIPSET_OPL3SA2) { arg_to_volume_mono(*(unsigned int*)arg, &devc->bass); opl3sa3_set_bass(devc, devc->bass); *(int*)arg = ret_vol_mono(devc->bass); return 0; } return -EINVAL; case SOUND_MIXER_TREBLE: if(chipset != CHIPSET_OPL3SA2) { arg_to_volume_mono(*(unsigned int *)arg, &devc->treble); opl3sa3_set_treble(devc, devc->treble); *(int*)arg = ret_vol_mono(devc->treble); return 0; } return -EINVAL; default: return -EINVAL; } } else { /* * Return parameters */ switch (cmdf) { case SOUND_MIXER_DEVMASK: if(call_ad_mixer(devc, cmd, arg) == -EINVAL) *(int*)arg = 0; /* no mixer devices */ *(int*)arg |= (SOUND_MASK_VOLUME | SOUND_MASK_MIC); /* OPL3-SA2 has no bass and treble mixers */ if(chipset != CHIPSET_OPL3SA2) *(int*)arg |= (SOUND_MASK_BASS | SOUND_MASK_TREBLE); return 0; case SOUND_MIXER_STEREODEVS: if(call_ad_mixer(devc, cmd, arg) == -EINVAL) *(int*)arg = 0; /* no stereo devices */ *(int*)arg |= SOUND_MASK_VOLUME; return 0; case SOUND_MIXER_RECMASK: if(devc->ad_mixer_dev != -1) { return call_ad_mixer(devc, cmd, arg); } else { /* No recording devices */ return (*(int*)arg = 0); } case SOUND_MIXER_CAPS: if(devc->ad_mixer_dev != -1) { return call_ad_mixer(devc, cmd, arg); } else { *(int*)arg = SOUND_CAP_EXCL_INPUT; return 0; } case SOUND_MIXER_RECSRC: if(devc->ad_mixer_dev != -1) { return call_ad_mixer(devc, cmd, arg); } else { /* No recording source */ return (*(int*)arg = 0); } case SOUND_MIXER_VOLUME: *(int*)arg = ret_vol_stereo(devc->volume_l, devc->volume_r); return 0; case SOUND_MIXER_MIC: *(int*)arg = ret_vol_mono(devc->mic); return 0; case SOUND_MIXER_BASS: if(chipset != CHIPSET_OPL3SA2) { *(int*)arg = ret_vol_mono(devc->bass); return 0; } else { return -EINVAL; } case SOUND_MIXER_TREBLE: if(chipset != CHIPSET_OPL3SA2) { *(int*)arg = ret_vol_mono(devc->treble); return 0; } else { return -EINVAL; } default: return -EINVAL; } } }
static int opl3sa3_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) { int cmdf = cmd & 0xff; opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc; switch(cmdf) { case SOUND_MIXER_BASS: case SOUND_MIXER_TREBLE: case SOUND_MIXER_DIGITAL1: case SOUND_MIXER_DEVMASK: case SOUND_MIXER_STEREODEVS: break; default: return opl3sa2_mixer_ioctl(dev, cmd, arg); } if(((cmd >> 8) & 0xff) != 'M') return -EINVAL; if(_SIOC_DIR (cmd) & _SIOC_WRITE) { switch (cmdf) { case SOUND_MIXER_BASS: arg_to_vol_stereo(*(unsigned int*)arg, &devc->bass_l, &devc->bass_r); opl3sa3_set_bass(devc, devc->bass_l, devc->bass_r); *(int*)arg = ret_vol_stereo(devc->bass_l, devc->bass_r); return 0; case SOUND_MIXER_TREBLE: arg_to_vol_stereo(*(unsigned int*)arg, &devc->treble_l, &devc->treble_r); opl3sa3_set_treble(devc, devc->treble_l, devc->treble_r); *(int*)arg = ret_vol_stereo(devc->treble_l, devc->treble_r); return 0; case SOUND_MIXER_DIGITAL1: arg_to_vol_stereo(*(unsigned int*)arg, &devc->wide_l, &devc->wide_r); opl3sa3_set_wide(devc, devc->wide_l, devc->wide_r); *(int*)arg = ret_vol_stereo(devc->wide_l, devc->wide_r); return 0; default: return -EINVAL; } } else { /* * Return parameters */ switch (cmdf) { case SOUND_MIXER_DEVMASK: *(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_DIGITAL1); return 0; case SOUND_MIXER_STEREODEVS: *(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_DIGITAL1); return 0; case SOUND_MIXER_BASS: *(int*)arg = ret_vol_stereo(devc->bass_l, devc->bass_r); return 0; case SOUND_MIXER_TREBLE: *(int*)arg = ret_vol_stereo(devc->treble_l, devc->treble_r); return 0; case SOUND_MIXER_DIGITAL1: *(int*)arg = ret_vol_stereo(devc->wide_l, devc->wide_r); return 0; default: return -EINVAL; } } }
static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) { int cmdf = cmd & 0xff; opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc; switch(cmdf) { case SOUND_MIXER_VOLUME: case SOUND_MIXER_MIC: case SOUND_MIXER_DEVMASK: case SOUND_MIXER_STEREODEVS: case SOUND_MIXER_RECMASK: case SOUND_MIXER_RECSRC: case SOUND_MIXER_CAPS: break; default: return -EINVAL; } if(((cmd >> 8) & 0xff) != 'M') return -EINVAL; if(_SIOC_DIR (cmd) & _SIOC_WRITE) { switch (cmdf) { case SOUND_MIXER_VOLUME: arg_to_vol_stereo(*(unsigned int*)arg, &devc->volume_l, &devc->volume_r); opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r); *(int*)arg = ret_vol_stereo(devc->volume_l, devc->volume_r); return 0; case SOUND_MIXER_MIC: arg_to_vol_mono(*(unsigned int*)arg, &devc->mic); opl3sa2_set_mic(devc, devc->mic); *(int*)arg = ret_vol_mono(devc->mic); return 0; default: return -EINVAL; } } else { /* * Return parameters */ switch (cmdf) { case SOUND_MIXER_DEVMASK: *(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_MIC); return 0; case SOUND_MIXER_STEREODEVS: *(int*)arg = SOUND_MASK_VOLUME; return 0; case SOUND_MIXER_RECMASK: /* No recording devices */ return (*(int*)arg = 0); case SOUND_MIXER_CAPS: *(int*)arg = SOUND_CAP_EXCL_INPUT; return 0; case SOUND_MIXER_RECSRC: /* No recording source */ return (*(int*)arg = 0); case SOUND_MIXER_VOLUME: *(int*)arg = ret_vol_stereo(devc->volume_l, devc->volume_r); return 0; case SOUND_MIXER_MIC: *(int*)arg = ret_vol_mono(devc->mic); return 0; default: return -EINVAL; } } }