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

📄 mixer_oss.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  OSS emulation layer for the mixer interface *  Copyright (c) by Jaroslav Kysela <perex@suse.cz> * * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * */#include <sound/driver.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/time.h>#include <sound/core.h>#include <sound/minors.h>#include <sound/control.h>#include <sound/info.h>#include <sound/mixer_oss.h>#include <linux/soundcard.h>MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");MODULE_DESCRIPTION("Mixer OSS emulation for ALSA.");MODULE_LICENSE("GPL");static inline void dec_mod_count(struct module *module){	if (module)		__MOD_DEC_USE_COUNT(module);}static int snd_mixer_oss_open(struct inode *inode, struct file *file){	int cardnum = SNDRV_MINOR_OSS_CARD(minor(inode->i_rdev));	snd_card_t *card;	snd_mixer_oss_file_t *fmixer;	if ((card = snd_cards[cardnum]) == NULL)		return -ENODEV;	if (card->mixer_oss == NULL)		return -ENODEV;	fmixer = (snd_mixer_oss_file_t *)snd_kcalloc(sizeof(*fmixer), GFP_KERNEL);	if (fmixer == NULL)		return -ENOMEM;	fmixer->card = card;	fmixer->mixer = card->mixer_oss;	file->private_data = fmixer;#ifdef LINUX_2_2	MOD_INC_USE_COUNT;#endif	if (!try_inc_mod_count(card->module)) {		kfree(fmixer);#ifdef LINUX_2_2		MOD_DEC_USE_COUNT;#endif		return -EFAULT;	}	return 0;}static int snd_mixer_oss_release(struct inode *inode, struct file *file){	snd_mixer_oss_file_t *fmixer;	if (file->private_data) {		fmixer = (snd_mixer_oss_file_t *) file->private_data;		dec_mod_count(fmixer->card->module);#ifdef LINUX_2_2		MOD_DEC_USE_COUNT;#endif		kfree(fmixer);	}	return 0;}static int snd_mixer_oss_info(snd_mixer_oss_file_t *fmixer,			      mixer_info *_info){	snd_card_t *card = fmixer->card;	snd_mixer_oss_t *mixer = fmixer->mixer;	struct mixer_info info;		memset(&info, 0, sizeof(info));	strncpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id) - 1);	strncpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name) - 1);	info.modify_counter = card->mixer_oss_change_count;	if (copy_to_user(_info, &info, sizeof(info)))		return -EFAULT;	return 0;}static int snd_mixer_oss_info_obsolete(snd_mixer_oss_file_t *fmixer,				       _old_mixer_info *_info){	snd_card_t *card = fmixer->card;	snd_mixer_oss_t *mixer = fmixer->mixer;	_old_mixer_info info;		memset(&info, 0, sizeof(info));	strncpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id) - 1);	strncpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name) - 1);	if (copy_to_user(_info, &info, sizeof(info)))		return -EFAULT;	return 0;}static int snd_mixer_oss_caps(snd_mixer_oss_file_t *fmixer){	snd_mixer_oss_t *mixer = fmixer->mixer;	int result = 0;	if (mixer == NULL)		return -EIO;	if (mixer->get_recsrc && mixer->put_recsrc)		result |= SOUND_CAP_EXCL_INPUT;	return result;}static int snd_mixer_oss_devmask(snd_mixer_oss_file_t *fmixer){	snd_mixer_oss_t *mixer = fmixer->mixer;	snd_mixer_oss_slot_t *pslot;	int result = 0, chn;	if (mixer == NULL)		return -EIO;	for (chn = 0; chn < 31; chn++) {		pslot = &mixer->slots[chn];		if (pslot->put_volume || pslot->put_recsrc)			result |= 1 << chn;	}	return result;}static int snd_mixer_oss_stereodevs(snd_mixer_oss_file_t *fmixer){	snd_mixer_oss_t *mixer = fmixer->mixer;	snd_mixer_oss_slot_t *pslot;	int result = 0, chn;	if (mixer == NULL)		return -EIO;	for (chn = 0; chn < 31; chn++) {		pslot = &mixer->slots[chn];		if (pslot->put_volume && pslot->stereo)			result |= 1 << chn;	}	return result;}static int snd_mixer_oss_recmask(snd_mixer_oss_file_t *fmixer){	snd_mixer_oss_t *mixer = fmixer->mixer;	int result = 0;	if (mixer == NULL)		return -EIO;	if (mixer->put_recsrc && mixer->get_recsrc) {	/* exclusive */		result = mixer->mask_recsrc;	} else {		snd_mixer_oss_slot_t *pslot;		int chn;		for (chn = 0; chn < 31; chn++) {			pslot = &mixer->slots[chn];			if (pslot->put_recsrc)				result |= 1 << chn;		}	}	return result;}static int snd_mixer_oss_get_recsrc(snd_mixer_oss_file_t *fmixer){	snd_mixer_oss_t *mixer = fmixer->mixer;	int result = 0;	if (mixer == NULL)		return -EIO;	if (mixer->put_recsrc && mixer->get_recsrc) {	/* exclusive */		int err;		if ((err = mixer->get_recsrc(fmixer, &result)) < 0)			return err;		result = 1 << result;	} else {		snd_mixer_oss_slot_t *pslot;		int chn;		for (chn = 0; chn < 31; chn++) {			pslot = &mixer->slots[chn];			if (pslot->get_recsrc) {				int active = 0;				pslot->get_recsrc(fmixer, pslot, &active);				if (active)					result |= 1 << chn;			}		}	}	return mixer->oss_recsrc = result;}static int snd_mixer_oss_set_recsrc(snd_mixer_oss_file_t *fmixer, int recsrc){	snd_mixer_oss_t *mixer = fmixer->mixer;	int result = 0;	if (mixer == NULL)		return -EIO;	if (mixer->get_recsrc && mixer->put_recsrc) {	/* exclusive input */		if (recsrc & ~mixer->oss_recsrc)			recsrc &= ~mixer->oss_recsrc;		mixer->put_recsrc(fmixer, ffz(~recsrc));		mixer->get_recsrc(fmixer, &result);		result = 1 << result;	} else {		snd_mixer_oss_slot_t *pslot;		int chn, active;		for (chn = 0; chn < 31; chn++) {			pslot = &mixer->slots[chn];			if (pslot->put_recsrc) {				active = (recsrc & (1 << chn)) ? 1 : 0;				pslot->put_recsrc(fmixer, pslot, active);			}		}		for (chn = 0; chn < 31; chn++) {			pslot = &mixer->slots[chn];			if (pslot->get_recsrc) {				active = 0;				pslot->get_recsrc(fmixer, pslot, &active);				if (active)					result |= 1 << chn;			}		}	}	return result;}static int snd_mixer_oss_get_volume(snd_mixer_oss_file_t *fmixer, int slot){	snd_mixer_oss_t *mixer = fmixer->mixer;	snd_mixer_oss_slot_t *pslot;	int result = 0, left, right;	if (mixer == NULL || slot > 30)		return -EIO;	pslot = &mixer->slots[slot];	left = fmixer->volume[slot][0];	right = fmixer->volume[slot][1];	if (pslot->get_volume)		result = pslot->get_volume(fmixer, pslot, &left, &right);	if (!pslot->stereo)		right = left;	snd_assert(left >= 0 && left <= 100, return -EIO);	snd_assert(right >= 0 && right <= 100, return -EIO);	if (result >= 0) {		fmixer->volume[slot][0] = left;		fmixer->volume[slot][1] = right;	 	result = (left & 0xff) | ((right & 0xff) << 8);	}	return result;}static int snd_mixer_oss_set_volume(snd_mixer_oss_file_t *fmixer,				    int slot, int volume){	snd_mixer_oss_t *mixer = fmixer->mixer;	snd_mixer_oss_slot_t *pslot;	int result = 0, left = volume & 0xff, right = (volume >> 8) & 0xff;	if (mixer == NULL || slot > 30)		return -EIO;	pslot = &mixer->slots[slot];	if (left > 100)		left = 100;	if (right > 100)		right = 100;	if (!pslot->stereo)		left = right = left;	if (pslot->put_volume)		result = pslot->put_volume(fmixer, pslot, left, right);	if (result < 0)		return result;	fmixer->volume[slot][0] = left;	fmixer->volume[slot][1] = right; 	return (left & 0xff) | ((right & 0xff) << 8);}static int snd_mixer_oss_ioctl1(snd_mixer_oss_file_t *fmixer, unsigned int cmd, unsigned long arg){	int tmp;	snd_assert(fmixer != NULL, return -ENXIO);	if (((cmd >> 8) & 0xff) == 'M') {		switch (cmd) {		case SOUND_MIXER_INFO:			return snd_mixer_oss_info(fmixer, (mixer_info *)arg);		case SOUND_OLD_MIXER_INFO: 			return snd_mixer_oss_info_obsolete(fmixer, (_old_mixer_info *)arg);		case SOUND_MIXER_WRITE_RECSRC:			if (get_user(tmp, (int *)arg))				return -EFAULT;			tmp = snd_mixer_oss_set_recsrc(fmixer, tmp);			if (tmp < 0)				return tmp;			return put_user(tmp, (int *)arg) ? -EFAULT : 0;		case OSS_GETVERSION:			return put_user(SNDRV_OSS_VERSION, (int *) arg);		case SOUND_MIXER_READ_DEVMASK:			tmp = snd_mixer_oss_devmask(fmixer);			if (tmp < 0)				return tmp;			return put_user(tmp, (int *)arg) ? -EFAULT : 0;		case SOUND_MIXER_READ_STEREODEVS:			tmp = snd_mixer_oss_stereodevs(fmixer);			if (tmp < 0)				return tmp;			return put_user(tmp, (int *)arg) ? -EFAULT : 0;		case SOUND_MIXER_READ_RECMASK:			tmp = snd_mixer_oss_recmask(fmixer);			if (tmp < 0)				return tmp;			return put_user(tmp, (int *)arg) ? -EFAULT : 0;		case SOUND_MIXER_READ_CAPS:			tmp = snd_mixer_oss_caps(fmixer);			if (tmp < 0)				return tmp;			return put_user(tmp, (int *)arg) ? -EFAULT : 0;		case SOUND_MIXER_READ_RECSRC:			tmp = snd_mixer_oss_get_recsrc(fmixer);			if (tmp < 0)				return tmp;			return put_user(tmp, (int *)arg) ? -EFAULT : 0;		}	}	if (cmd & IOC_IN) {		if (get_user(tmp, (int *)arg))			return -EFAULT;		tmp = snd_mixer_oss_set_volume(fmixer, cmd & 0xff, tmp);		if (tmp < 0)			return tmp;

⌨️ 快捷键说明

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