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

📄 mixer_oss.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
static void snd_mixer_oss_slot_free(snd_mixer_oss_slot_t *chn){	struct slot *p = (struct slot *)chn->private_data;	if (p) {		if (p->allocated && p->assigned) {			kfree(p->assigned->name);			kfree(p->assigned);		}		kfree(p);	}}static void mixer_slot_clear(snd_mixer_oss_slot_t *rslot){	int idx = rslot->number; /* remember this */	if (rslot->private_free)		rslot->private_free(rslot);	memset(rslot, 0, sizeof(*rslot));	rslot->number = idx;}/* * build an OSS mixer element. * ptr_allocated means the entry is dynamically allocated (change via proc file). * when replace_old = 1, the old entry is replaced with the new one. */static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_oss_assign_table *ptr, int ptr_allocated, int replace_old){	struct slot slot;	struct slot *pslot;	snd_kcontrol_t *kctl;	snd_mixer_oss_slot_t *rslot;	char str[64];			/* check if already assigned */	if (mixer->slots[ptr->oss_id].get_volume && ! replace_old)		return 0;	memset(&slot, 0, sizeof(slot));	memset(slot.numid, 0xff, sizeof(slot.numid)); /* ID_UNKNOWN */	if (snd_mixer_oss_build_test(mixer, &slot, ptr->name, ptr->index,				     SNDRV_MIXER_OSS_ITEM_GLOBAL))		return 0;	sprintf(str, "%s Switch", ptr->name);	if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index,				     SNDRV_MIXER_OSS_ITEM_GSWITCH))		return 0;	sprintf(str, "%s Route", ptr->name);	if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index,				     SNDRV_MIXER_OSS_ITEM_GROUTE))		return 0;	sprintf(str, "%s Volume", ptr->name);	if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index,				     SNDRV_MIXER_OSS_ITEM_GVOLUME))		return 0;	sprintf(str, "%s Playback Switch", ptr->name);	if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index,				     SNDRV_MIXER_OSS_ITEM_PSWITCH))		return 0;	sprintf(str, "%s Playback Route", ptr->name);	if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index,				     SNDRV_MIXER_OSS_ITEM_PROUTE))		return 0;	sprintf(str, "%s Playback Volume", ptr->name);	if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index,				     SNDRV_MIXER_OSS_ITEM_PVOLUME))		return 0;	sprintf(str, "%s Capture Switch", ptr->name);	if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index,				     SNDRV_MIXER_OSS_ITEM_CSWITCH))		return 0;	sprintf(str, "%s Capture Route", ptr->name);	if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index,				     SNDRV_MIXER_OSS_ITEM_CROUTE))		return 0;	sprintf(str, "%s Capture Volume", ptr->name);	if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index,				     SNDRV_MIXER_OSS_ITEM_CVOLUME))		return 0;	down_read(&mixer->card->controls_rwsem);	if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) {		snd_ctl_elem_info_t *uinfo;		uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);		if (! uinfo) {			up_read(&mixer->card->controls_rwsem);			return -ENOMEM;		}					memset(uinfo, 0, sizeof(*uinfo));		if (kctl->info(kctl, uinfo)) {			up_read(&mixer->card->controls_rwsem);			return 0;		}		strcpy(str, ptr->name);		if (!strcmp(str, "Master"))			strcpy(str, "Mix");		if (!strcmp(str, "Master Mono"))			strcpy(str, "Mix Mono");		slot.capture_item = 0;		if (!strcmp(uinfo->value.enumerated.name, str)) {			slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE;		} else {			for (slot.capture_item = 1; slot.capture_item < uinfo->value.enumerated.items; slot.capture_item++) {				uinfo->value.enumerated.item = slot.capture_item;				if (kctl->info(kctl, uinfo)) {					up_read(&mixer->card->controls_rwsem);					return 0;				}				if (!strcmp(uinfo->value.enumerated.name, str)) {					slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE;					break;				}			}		}		kfree(uinfo);	}	up_read(&mixer->card->controls_rwsem);	if (slot.present != 0) {		pslot = (struct slot *)kmalloc(sizeof(slot), GFP_KERNEL);		if (! pslot)			return -ENOMEM;		*pslot = slot;		pslot->signature = SNDRV_MIXER_OSS_SIGNATURE;		pslot->assigned = ptr;		pslot->allocated = ptr_allocated;		rslot = &mixer->slots[ptr->oss_id];		mixer_slot_clear(rslot);		rslot->stereo = slot.channels > 1 ? 1 : 0;		rslot->get_volume = snd_mixer_oss_get_volume1;		rslot->put_volume = snd_mixer_oss_put_volume1;		/* note: ES18xx have both Capture Source and XX Capture Volume !!! */		if (slot.present & SNDRV_MIXER_OSS_PRESENT_CSWITCH) {			rslot->get_recsrc = snd_mixer_oss_get_recsrc1_sw;			rslot->put_recsrc = snd_mixer_oss_put_recsrc1_sw;		} else if (slot.present & SNDRV_MIXER_OSS_PRESENT_CROUTE) {			rslot->get_recsrc = snd_mixer_oss_get_recsrc1_route;			rslot->put_recsrc = snd_mixer_oss_put_recsrc1_route;		} else if (slot.present & SNDRV_MIXER_OSS_PRESENT_CAPTURE) {			mixer->mask_recsrc |= 1 << ptr->oss_id;		}		rslot->private_data = pslot;		rslot->private_free = snd_mixer_oss_slot_free;		return 1;	}	return 0;}/* */#define MIXER_VOL(name) [SOUND_MIXER_##name] = #namestatic char *oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = {	MIXER_VOL(VOLUME),	MIXER_VOL(BASS),	MIXER_VOL(TREBLE),	MIXER_VOL(SYNTH),	MIXER_VOL(PCM),	MIXER_VOL(SPEAKER),	MIXER_VOL(LINE),	MIXER_VOL(MIC),	MIXER_VOL(CD),	MIXER_VOL(IMIX),	MIXER_VOL(ALTPCM),	MIXER_VOL(RECLEV),	MIXER_VOL(IGAIN),	MIXER_VOL(OGAIN),	MIXER_VOL(LINE1),	MIXER_VOL(LINE2),	MIXER_VOL(LINE3),	MIXER_VOL(DIGITAL1),	MIXER_VOL(DIGITAL2),	MIXER_VOL(DIGITAL3),	MIXER_VOL(PHONEIN),	MIXER_VOL(PHONEOUT),	MIXER_VOL(VIDEO),	MIXER_VOL(RADIO),	MIXER_VOL(MONITOR),};	/* *  /proc interface */static void snd_mixer_oss_proc_read(snd_info_entry_t *entry,				    snd_info_buffer_t * buffer){	snd_mixer_oss_t *mixer = entry->private_data;	int i;	down(&mixer->reg_mutex);	for (i = 0; i < SNDRV_OSS_MAX_MIXERS; i++) {		struct slot *p;		if (! oss_mixer_names[i])			continue;		p = (struct slot *)mixer->slots[i].private_data;		snd_iprintf(buffer, "%s ", oss_mixer_names[i]);		if (p && p->assigned)			snd_iprintf(buffer, "\"%s\" %d\n",				    p->assigned->name,				    p->assigned->index);		else			snd_iprintf(buffer, "\"\" 0\n");	}	up(&mixer->reg_mutex);}static void snd_mixer_oss_proc_write(snd_info_entry_t *entry,				     snd_info_buffer_t * buffer){	snd_mixer_oss_t *mixer = entry->private_data;	char line[128], str[32], idxstr[16], *cptr;	int ch, idx;	struct snd_mixer_oss_assign_table *tbl;	struct slot *slot;	while (!snd_info_get_line(buffer, line, sizeof(line))) {		cptr = snd_info_get_str(str, line, sizeof(str));		for (ch = 0; ch < SNDRV_OSS_MAX_MIXERS; ch++)			if (oss_mixer_names[ch] && strcmp(oss_mixer_names[ch], str) == 0)				break;		if (ch >= SNDRV_OSS_MAX_MIXERS) {			snd_printk(KERN_ERR "mixer_oss: invalid OSS volume '%s'\n", str);			continue;		}		cptr = snd_info_get_str(str, cptr, sizeof(str));		if (! *str) {			/* remove the entry */			down(&mixer->reg_mutex);			mixer_slot_clear(&mixer->slots[ch]);			up(&mixer->reg_mutex);			continue;		}		snd_info_get_str(idxstr, cptr, sizeof(idxstr));		idx = simple_strtoul(idxstr, NULL, 10);		if (idx >= 0x4000) { /* too big */			snd_printk(KERN_ERR "mixer_oss: invalid index %d\n", idx);			continue;		}		down(&mixer->reg_mutex);		slot = (struct slot *)mixer->slots[ch].private_data;		if (slot && slot->assigned &&		    slot->assigned->index == idx && ! strcmp(slot->assigned->name, str))			/* not changed */			goto __unlock;		tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);		if (! tbl) {			snd_printk(KERN_ERR "mixer_oss: no memory\n");			goto __unlock;		}		tbl->oss_id = ch;		tbl->name = kstrdup(str, GFP_KERNEL);		if (! tbl->name) {			kfree(tbl);			goto __unlock;		}		tbl->index = idx;		if (snd_mixer_oss_build_input(mixer, tbl, 1, 1) <= 0) {			kfree(tbl->name);			kfree(tbl);		}	__unlock:		up(&mixer->reg_mutex);	}}static void snd_mixer_oss_proc_init(snd_mixer_oss_t *mixer){	snd_info_entry_t *entry;	entry = snd_info_create_card_entry(mixer->card, "oss_mixer",					   mixer->card->proc_root);	if (! entry)		return;	entry->content = SNDRV_INFO_CONTENT_TEXT;	entry->mode = S_IFREG | S_IRUGO | S_IWUSR;	entry->c.text.read_size = 8192;	entry->c.text.read = snd_mixer_oss_proc_read;	entry->c.text.write_size = 8192;	entry->c.text.write = snd_mixer_oss_proc_write;	entry->private_data = mixer;	if (snd_info_register(entry) < 0) {		snd_info_free_entry(entry);		entry = NULL;	}	mixer->proc_entry = entry;}static void snd_mixer_oss_proc_done(snd_mixer_oss_t *mixer){	if (mixer->proc_entry) {		snd_info_unregister(mixer->proc_entry);		mixer->proc_entry = NULL;	}}static void snd_mixer_oss_build(snd_mixer_oss_t *mixer){	static struct snd_mixer_oss_assign_table table[] = {		{ SOUND_MIXER_VOLUME, 	"Master",		0 },		{ SOUND_MIXER_VOLUME, 	"Front",		0 }, /* fallback */		{ SOUND_MIXER_BASS,	"Tone Control - Bass",	0 },		{ SOUND_MIXER_TREBLE,	"Tone Control - Treble", 0 },		{ SOUND_MIXER_SYNTH,	"Synth",		0 },		{ SOUND_MIXER_SYNTH,	"FM",			0 }, /* fallback */		{ SOUND_MIXER_SYNTH,	"Music",		0 }, /* fallback */		{ SOUND_MIXER_PCM,	"PCM",			0 },		{ SOUND_MIXER_SPEAKER,	"PC Speaker", 		0 },		{ SOUND_MIXER_LINE,	"Line", 		0 },		{ SOUND_MIXER_MIC,	"Mic", 			0 },		{ SOUND_MIXER_CD,	"CD", 			0 },		{ SOUND_MIXER_IMIX,	"Monitor Mix", 		0 },		{ SOUND_MIXER_ALTPCM,	"PCM",			1 },		{ SOUND_MIXER_ALTPCM,	"Headphone",		0 }, /* fallback */		{ SOUND_MIXER_ALTPCM,	"Wave",			0 }, /* fallback */		{ SOUND_MIXER_RECLEV,	"-- nothing --",	0 },		{ SOUND_MIXER_IGAIN,	"Capture",		0 },		{ SOUND_MIXER_OGAIN,	"Playback",		0 },		{ SOUND_MIXER_LINE1,	"Aux",			0 },		{ SOUND_MIXER_LINE2,	"Aux",			1 },		{ SOUND_MIXER_LINE3,	"Aux",			2 },		{ SOUND_MIXER_DIGITAL1,	"Digital",		0 },		{ SOUND_MIXER_DIGITAL1,	"IEC958",		0 }, /* fallback */		{ SOUND_MIXER_DIGITAL1,	"IEC958 Optical",	0 }, /* fallback */		{ SOUND_MIXER_DIGITAL1,	"IEC958 Coaxial",	0 }, /* fallback */		{ SOUND_MIXER_DIGITAL2,	"Digital",		1 },		{ SOUND_MIXER_DIGITAL3,	"Digital",		2 },		{ SOUND_MIXER_PHONEIN,	"Phone",		0 },		{ SOUND_MIXER_PHONEOUT,	"Master Mono",		0 },		{ SOUND_MIXER_PHONEOUT,	"Phone",		0 }, /* fallback */		{ SOUND_MIXER_VIDEO,	"Video",		0 },		{ SOUND_MIXER_RADIO,	"Radio",		0 },		{ SOUND_MIXER_MONITOR,	"Monitor",		0 }	};	unsigned int idx;		for (idx = 0; idx < ARRAY_SIZE(table); idx++)		snd_mixer_oss_build_input(mixer, &table[idx], 0, 0);	if (mixer->mask_recsrc) {		mixer->get_recsrc = snd_mixer_oss_get_recsrc2;		mixer->put_recsrc = snd_mixer_oss_put_recsrc2;	}}/* * */static int snd_mixer_oss_free1(void *private){	snd_mixer_oss_t *mixer = private;	snd_card_t * card;	int idx; 	snd_assert(mixer != NULL, return -ENXIO);	card = mixer->card;	snd_assert(mixer == card->mixer_oss, return -ENXIO);	card->mixer_oss = NULL;	for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++) {		snd_mixer_oss_slot_t *chn = &mixer->slots[idx];		if (chn->private_free)			chn->private_free(chn);	}	kfree(mixer);	return 0;}static int snd_mixer_oss_notify_handler(snd_card_t * card, int cmd){	snd_mixer_oss_t *mixer;	if (cmd == SND_MIXER_OSS_NOTIFY_REGISTER) {		char name[128];		int idx, err;		mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL);		if (mixer == NULL)			return -ENOMEM;		init_MUTEX(&mixer->reg_mutex);		sprintf(name, "mixer%i%i", card->number, 0);		if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER,						   card, 0,						   &snd_mixer_oss_reg,						   name)) < 0) {			snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n",				   card->number, 0);			kfree(mixer);			return err;		}		mixer->oss_dev_alloc = 1;		mixer->card = card;		if (*card->mixername)			strlcpy(mixer->name, card->mixername, sizeof(mixer->name));		else			strlcpy(mixer->name, name, sizeof(mixer->name));#ifdef SNDRV_OSS_INFO_DEV_MIXERS		snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIXERS,				      card->number,				      mixer->name);#endif		for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++)			mixer->slots[idx].number = idx;		card->mixer_oss = mixer;		snd_mixer_oss_build(mixer);		snd_mixer_oss_proc_init(mixer);	} else if (cmd == SND_MIXER_OSS_NOTIFY_DISCONNECT) {		mixer = card->mixer_oss;		if (mixer == NULL || !mixer->oss_dev_alloc)			return 0;		snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0);		mixer->oss_dev_alloc = 0;	} else {		/* free */		mixer = card->mixer_oss;		if (mixer == NULL)			return 0;#ifdef SNDRV_OSS_INFO_DEV_MIXERS		snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIXERS, mixer->card->number);#endif		if (mixer->oss_dev_alloc)			snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0);		snd_mixer_oss_proc_done(mixer);		return snd_mixer_oss_free1(mixer);	}	return 0;}static int __init alsa_mixer_oss_init(void){	int idx;		snd_mixer_oss_notify_callback = snd_mixer_oss_notify_handler;	for (idx = 0; idx < SNDRV_CARDS; idx++) {		if (snd_cards[idx])			snd_mixer_oss_notify_handler(snd_cards[idx], SND_MIXER_OSS_NOTIFY_REGISTER);	}	return 0;}static void __exit alsa_mixer_oss_exit(void){	int idx;	snd_mixer_oss_notify_callback = NULL;	for (idx = 0; idx < SNDRV_CARDS; idx++) {		if (snd_cards[idx])			snd_mixer_oss_notify_handler(snd_cards[idx], SND_MIXER_OSS_NOTIFY_FREE);	}}module_init(alsa_mixer_oss_init)module_exit(alsa_mixer_oss_exit)EXPORT_SYMBOL(snd_mixer_oss_ioctl_card);

⌨️ 快捷键说明

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